diff options
Diffstat (limited to 'servers/rendering/renderer_rd')
87 files changed, 5006 insertions, 2788 deletions
diff --git a/servers/rendering/renderer_rd/SCsub b/servers/rendering/renderer_rd/SCsub index 774a6b7951..10b83dca11 100644 --- a/servers/rendering/renderer_rd/SCsub +++ b/servers/rendering/renderer_rd/SCsub @@ -5,6 +5,7 @@ Import("env") env.add_source_files(env.servers_sources, "*.cpp") SConscript("effects/SCsub") +SConscript("environment/SCsub") SConscript("forward_clustered/SCsub") SConscript("forward_mobile/SCsub") SConscript("shaders/SCsub") diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp index 0b36fe3964..228933d618 100644 --- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp +++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp @@ -413,7 +413,7 @@ void ClusterBuilderRD::bake_cluster() { StateUniform state; - RendererStorageRD::store_camera(adjusted_projection, state.projection); + RendererRD::MaterialStorage::store_camera(adjusted_projection, state.projection); state.inv_z_far = 1.0 / z_far; state.screen_to_clusters_shift = get_shift_from_power_of_2(cluster_size); state.screen_to_clusters_shift -= divisor; //screen is smaller, shift one less diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.h b/servers/rendering/renderer_rd/cluster_builder_rd.h index e82193ea6a..74ca530ff6 100644 --- a/servers/rendering/renderer_rd/cluster_builder_rd.h +++ b/servers/rendering/renderer_rd/cluster_builder_rd.h @@ -31,10 +31,10 @@ #ifndef CLUSTER_BUILDER_RD_H #define CLUSTER_BUILDER_RD_H -#include "servers/rendering/renderer_rd/renderer_storage_rd.h" #include "servers/rendering/renderer_rd/shaders/cluster_debug.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/cluster_render.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/cluster_store.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" class ClusterBuilderSharedDataRD { friend class ClusterBuilderRD; @@ -261,7 +261,7 @@ public: e.type = ELEMENT_TYPE_OMNI_LIGHT; e.original_index = cluster_count_by_type[ELEMENT_TYPE_OMNI_LIGHT]; - RendererStorageRD::store_transform_transposed_3x4(xform, e.transform_inv); + RendererRD::MaterialStorage::store_transform_transposed_3x4(xform, e.transform_inv); cluster_count_by_type[ELEMENT_TYPE_OMNI_LIGHT]++; @@ -309,7 +309,7 @@ public: e.type = ELEMENT_TYPE_SPOT_LIGHT; e.original_index = cluster_count_by_type[ELEMENT_TYPE_SPOT_LIGHT]; //use omni since they share index - RendererStorageRD::store_transform_transposed_3x4(xform, e.transform_inv); + RendererRD::MaterialStorage::store_transform_transposed_3x4(xform, e.transform_inv); cluster_count_by_type[ELEMENT_TYPE_SPOT_LIGHT]++; } @@ -356,7 +356,7 @@ public: e.type = (p_box_type == BOX_TYPE_DECAL) ? ELEMENT_TYPE_DECAL : ELEMENT_TYPE_REFLECTION_PROBE; e.original_index = cluster_count_by_type[e.type]; - RendererStorageRD::store_transform_transposed_3x4(xform, e.transform_inv); + RendererRD::MaterialStorage::store_transform_transposed_3x4(xform, e.transform_inv); cluster_count_by_type[e.type]++; render_element_count++; diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp index 6b786fdf16..cbf7046887 100644 --- a/servers/rendering/renderer_rd/effects/copy_effects.cpp +++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp @@ -29,9 +29,11 @@ /*************************************************************************/ #include "copy_effects.h" +#include "core/config/project_settings.h" #include "servers/rendering/renderer_rd/renderer_compositor_rd.h" #include "servers/rendering/renderer_rd/storage_rd/material_storage.h" #include "servers/rendering/renderer_rd/uniform_set_cache_rd.h" +#include "thirdparty/misc/cubemap_coeffs.h" using namespace RendererRD; @@ -98,11 +100,11 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) { { Vector<String> copy_modes; - copy_modes.push_back("\n"); - copy_modes.push_back("\n#define MODE_PANORAMA_TO_DP\n"); - copy_modes.push_back("\n#define MODE_TWO_SOURCES\n"); - copy_modes.push_back("\n#define MULTIVIEW\n"); - copy_modes.push_back("\n#define MULTIVIEW\n#define MODE_TWO_SOURCES\n"); + copy_modes.push_back("\n"); // COPY_TO_FB_COPY + copy_modes.push_back("\n#define MODE_PANORAMA_TO_DP\n"); // COPY_TO_FB_COPY_PANORAMA_TO_DP + copy_modes.push_back("\n#define MODE_TWO_SOURCES\n"); // COPY_TO_FB_COPY2 + copy_modes.push_back("\n#define MULTIVIEW\n"); // COPY_TO_FB_MULTIVIEW + copy_modes.push_back("\n#define MULTIVIEW\n#define MODE_TWO_SOURCES\n"); // COPY_TO_FB_MULTIVIEW_WITH_DEPTH copy_to_fb.shader.initialize(copy_modes); @@ -123,16 +125,157 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) { } } } + + { + // Initialize copier + Vector<String> copy_modes; + copy_modes.push_back("\n"); + + cube_to_dp.shader.initialize(copy_modes); + + cube_to_dp.shader_version = cube_to_dp.shader.version_create(); + RID shader = cube_to_dp.shader.version_get_shader(cube_to_dp.shader_version, 0); + RD::PipelineDepthStencilState dss; + dss.enable_depth_test = true; + dss.depth_compare_operator = RD::COMPARE_OP_ALWAYS; + dss.enable_depth_write = true; + cube_to_dp.pipeline.setup(shader, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), dss, RD::PipelineColorBlendState(), 0); + } + + { + //Initialize cubemap downsampler + Vector<String> cubemap_downsampler_modes; + cubemap_downsampler_modes.push_back(""); + + if (prefer_raster_effects) { + cubemap_downsampler.raster_shader.initialize(cubemap_downsampler_modes); + + cubemap_downsampler.shader_version = cubemap_downsampler.raster_shader.version_create(); + + cubemap_downsampler.raster_pipeline.setup(cubemap_downsampler.raster_shader.version_get_shader(cubemap_downsampler.shader_version, 0), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); + } else { + cubemap_downsampler.compute_shader.initialize(cubemap_downsampler_modes); + + cubemap_downsampler.shader_version = cubemap_downsampler.compute_shader.version_create(); + + cubemap_downsampler.compute_pipeline = RD::get_singleton()->compute_pipeline_create(cubemap_downsampler.compute_shader.version_get_shader(cubemap_downsampler.shader_version, 0)); + cubemap_downsampler.raster_pipeline.clear(); + } + } + + { + // Initialize cubemap filter + filter.use_high_quality = GLOBAL_GET("rendering/reflections/sky_reflections/fast_filter_high_quality"); + + Vector<String> cubemap_filter_modes; + cubemap_filter_modes.push_back("\n#define USE_HIGH_QUALITY\n"); + cubemap_filter_modes.push_back("\n#define USE_LOW_QUALITY\n"); + cubemap_filter_modes.push_back("\n#define USE_HIGH_QUALITY\n#define USE_TEXTURE_ARRAY\n"); + cubemap_filter_modes.push_back("\n#define USE_LOW_QUALITY\n#define USE_TEXTURE_ARRAY\n"); + + if (filter.use_high_quality) { + filter.coefficient_buffer = RD::get_singleton()->storage_buffer_create(sizeof(high_quality_coeffs)); + RD::get_singleton()->buffer_update(filter.coefficient_buffer, 0, sizeof(high_quality_coeffs), &high_quality_coeffs[0]); + } else { + filter.coefficient_buffer = RD::get_singleton()->storage_buffer_create(sizeof(low_quality_coeffs)); + RD::get_singleton()->buffer_update(filter.coefficient_buffer, 0, sizeof(low_quality_coeffs), &low_quality_coeffs[0]); + } + + if (prefer_raster_effects) { + filter.raster_shader.initialize(cubemap_filter_modes); + + // array variants are not supported in raster + filter.raster_shader.set_variant_enabled(FILTER_MODE_HIGH_QUALITY_ARRAY, false); + filter.raster_shader.set_variant_enabled(FILTER_MODE_LOW_QUALITY_ARRAY, false); + + filter.shader_version = filter.raster_shader.version_create(); + + for (int i = 0; i < FILTER_MODE_MAX; i++) { + if (filter.raster_shader.is_variant_enabled(i)) { + filter.raster_pipelines[i].setup(filter.raster_shader.version_get_shader(filter.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); + } else { + filter.raster_pipelines[i].clear(); + } + } + + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 0; + u.append_id(filter.coefficient_buffer); + uniforms.push_back(u); + } + filter.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.raster_shader.version_get_shader(filter.shader_version, filter.use_high_quality ? 0 : 1), 1); + } else { + filter.compute_shader.initialize(cubemap_filter_modes); + filter.shader_version = filter.compute_shader.version_create(); + + for (int i = 0; i < FILTER_MODE_MAX; i++) { + filter.compute_pipelines[i] = RD::get_singleton()->compute_pipeline_create(filter.compute_shader.version_get_shader(filter.shader_version, i)); + filter.raster_pipelines[i].clear(); + } + + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 0; + u.append_id(filter.coefficient_buffer); + uniforms.push_back(u); + } + filter.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.compute_shader.version_get_shader(filter.shader_version, filter.use_high_quality ? 0 : 1), 1); + } + } + + { + // Initialize roughness + Vector<String> cubemap_roughness_modes; + cubemap_roughness_modes.push_back(""); + + if (prefer_raster_effects) { + roughness.raster_shader.initialize(cubemap_roughness_modes); + + roughness.shader_version = roughness.raster_shader.version_create(); + + roughness.raster_pipeline.setup(roughness.raster_shader.version_get_shader(roughness.shader_version, 0), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); + + } else { + roughness.compute_shader.initialize(cubemap_roughness_modes); + + roughness.shader_version = roughness.compute_shader.version_create(); + + roughness.compute_pipeline = RD::get_singleton()->compute_pipeline_create(roughness.compute_shader.version_get_shader(roughness.shader_version, 0)); + roughness.raster_pipeline.clear(); + } + } } CopyEffects::~CopyEffects() { if (prefer_raster_effects) { blur_raster.shader.version_free(blur_raster.shader_version); + cubemap_downsampler.raster_shader.version_free(cubemap_downsampler.shader_version); + filter.raster_shader.version_free(filter.shader_version); + roughness.raster_shader.version_free(roughness.shader_version); } else { copy.shader.version_free(copy.shader_version); + cubemap_downsampler.compute_shader.version_free(cubemap_downsampler.shader_version); + filter.compute_shader.version_free(filter.shader_version); + roughness.compute_shader.version_free(roughness.shader_version); + } + + RD::get_singleton()->free(filter.coefficient_buffer); + + if (RD::get_singleton()->uniform_set_is_valid(filter.image_uniform_set)) { + RD::get_singleton()->free(filter.image_uniform_set); + } + + if (RD::get_singleton()->uniform_set_is_valid(filter.uniform_set)) { + RD::get_singleton()->free(filter.uniform_set); } copy_to_fb.shader.version_free(copy_to_fb.shader_version); + cube_to_dp.shader.version_free(cube_to_dp.shader_version); singleton = nullptr; } @@ -681,3 +824,262 @@ void CopyEffects::set_color(RID p_dest_texture, const Color &p_color, const Rect RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_region.size.width, p_region.size.height, 1); RD::get_singleton()->compute_list_end(); } + +void CopyEffects::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + CopyToDPPushConstant push_constant; + push_constant.screen_rect[0] = p_rect.position.x; + push_constant.screen_rect[1] = p_rect.position.y; + push_constant.screen_rect[2] = p_rect.size.width; + push_constant.screen_rect[3] = p_rect.size.height; + push_constant.z_far = p_z_far; + push_constant.z_near = p_z_near; + push_constant.texel_size[0] = 1.0f / p_dst_size.x; + push_constant.texel_size[1] = 1.0f / p_dst_size.y; + push_constant.texel_size[0] *= p_dp_flip ? -1.0f : 1.0f; // Encode dp flip as x size sign + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); + + RID shader = cube_to_dp.shader.version_get_shader(cube_to_dp.shader_version, 0); + ERR_FAIL_COND(shader.is_null()); + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, cube_to_dp.pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_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, &push_constant, sizeof(CopyToDPPushConstant)); + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_TRANSFER); +} + +void CopyEffects::cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size) { + ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute based cubemap downsample with the mobile renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + cubemap_downsampler.push_constant.face_size = p_size.x; + cubemap_downsampler.push_constant.face_id = 0; // we render all 6 sides to each layer in one call + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_cubemap(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_cubemap })); + RD::Uniform u_dest_cubemap(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_dest_cubemap })); + + RID shader = cubemap_downsampler.compute_shader.version_get_shader(cubemap_downsampler.shader_version, 0); + ERR_FAIL_COND(shader.is_null()); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, cubemap_downsampler.compute_pipeline); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_cubemap), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_dest_cubemap), 1); + + int x_groups = (p_size.x - 1) / 8 + 1; + int y_groups = (p_size.y - 1) / 8 + 1; + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &cubemap_downsampler.push_constant, sizeof(CubemapDownsamplerPushConstant)); + + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 6); // one z_group for each face + + RD::get_singleton()->compute_list_end(); +} + +void CopyEffects::cubemap_downsample_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, const Size2i &p_size) { + ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use raster based cubemap downsample with the clustered renderer."); + ERR_FAIL_COND_MSG(p_face_id >= 6, "Raster implementation of cubemap downsample must process one side at a time."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + cubemap_downsampler.push_constant.face_size = p_size.x; + cubemap_downsampler.push_constant.face_id = p_face_id; + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_cubemap(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_cubemap })); + + RID shader = cubemap_downsampler.raster_shader.version_get_shader(cubemap_downsampler.shader_version, 0); + ERR_FAIL_COND(shader.is_null()); + + 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_end(); +} + +void CopyEffects::cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array) { + ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute based cubemap filter with the mobile renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + Vector<RD::Uniform> uniforms; + for (int i = 0; i < p_dest_cubemap.size(); i++) { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = i; + u.append_id(p_dest_cubemap[i]); + uniforms.push_back(u); + } + if (RD::get_singleton()->uniform_set_is_valid(filter.image_uniform_set)) { + RD::get_singleton()->free(filter.image_uniform_set); + } + filter.image_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.compute_shader.version_get_shader(filter.shader_version, 0), 2); + + // setup our uniforms + RID default_mipmap_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_cubemap(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_mipmap_sampler, p_source_cubemap })); + + int mode = p_use_array ? FILTER_MODE_HIGH_QUALITY_ARRAY : FILTER_MODE_HIGH_QUALITY; + mode = filter.use_high_quality ? mode : mode + 1; + + RID shader = filter.compute_shader.version_get_shader(filter.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, filter.compute_pipelines[mode]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_cubemap), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, filter.uniform_set, 1); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, filter.image_uniform_set, 2); + + int x_groups = p_use_array ? 1792 : 342; // (128 * 128 * 7) / 64 : (128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2) / 64 + + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, 6, 1); // one y_group for each face + + RD::get_singleton()->compute_list_end(); +} + +void CopyEffects::cubemap_filter_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_mip_level) { + ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use raster based cubemap filter with the clustered renderer."); + ERR_FAIL_COND_MSG(p_face_id >= 6, "Raster implementation of cubemap filter must process one side at a time."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + // TODO implement! + CubemapFilterRasterPushConstant push_constant; + push_constant.mip_level = p_mip_level; + push_constant.face_id = p_face_id; + + // setup our uniforms + RID default_mipmap_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_cubemap(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_mipmap_sampler, p_source_cubemap })); + + CubemapFilterMode mode = filter.use_high_quality ? FILTER_MODE_HIGH_QUALITY : FILTER_MODE_LOW_QUALITY; + + RID shader = filter.raster_shader.version_get_shader(filter.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + 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, 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_end(); +} + +void CopyEffects::cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size) { + ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute based cubemap roughness with the mobile renderer."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(&roughness.push_constant, 0, sizeof(CubemapRoughnessPushConstant)); + + roughness.push_constant.face_id = p_face_id > 9 ? 0 : p_face_id; + roughness.push_constant.roughness = p_roughness * p_roughness; // Shader expects roughness, not perceptual roughness, so multiply before passing in. + roughness.push_constant.sample_count = p_sample_count; + roughness.push_constant.use_direct_write = p_roughness == 0.0; + roughness.push_constant.face_size = p_size; + + // setup our uniforms + RID default_mipmap_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_mipmap_sampler, p_source_rd_texture })); + RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_dest_texture })); + + RID shader = roughness.compute_shader.version_get_shader(roughness.shader_version, 0); + ERR_FAIL_COND(shader.is_null()); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, roughness.compute_pipeline); + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_dest_texture), 1); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &roughness.push_constant, sizeof(CubemapRoughnessPushConstant)); + + int x_groups = (p_size - 1) / 8 + 1; + int y_groups = (p_size - 1) / 8 + 1; + + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, p_face_id > 9 ? 6 : 1); + + RD::get_singleton()->compute_list_end(); +} + +void CopyEffects::cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size) { + ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use raster based cubemap roughness with the clustered renderer."); + ERR_FAIL_COND_MSG(p_face_id >= 6, "Raster implementation of cubemap roughness must process one side at a time."); + + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + memset(&roughness.push_constant, 0, sizeof(CubemapRoughnessPushConstant)); + + roughness.push_constant.face_id = p_face_id; + roughness.push_constant.roughness = p_roughness * p_roughness; // Shader expects roughness, not perceptual roughness, so multiply before passing in. + roughness.push_constant.sample_count = p_sample_count; + roughness.push_constant.use_direct_write = p_roughness == 0.0; + roughness.push_constant.face_size = p_size; + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); + + RID shader = roughness.raster_shader.version_get_shader(roughness.shader_version, 0); + ERR_FAIL_COND(shader.is_null()); + + 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_end(); +} diff --git a/servers/rendering/renderer_rd/effects/copy_effects.h b/servers/rendering/renderer_rd/effects/copy_effects.h index e522408d20..882b446964 100644 --- a/servers/rendering/renderer_rd/effects/copy_effects.h +++ b/servers/rendering/renderer_rd/effects/copy_effects.h @@ -35,6 +35,13 @@ #include "servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/effects/copy.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/cube_to_dp.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler_raster.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/cubemap_filter.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/cubemap_filter_raster.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/cubemap_roughness.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_raster.glsl.gen.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering_server.h" @@ -189,6 +196,84 @@ private: } copy_to_fb; + // Copy to DP + + struct CopyToDPPushConstant { + float z_far; + float z_near; + float texel_size[2]; + float screen_rect[4]; + }; + + struct CopyToDP { + CubeToDpShaderRD shader; + RID shader_version; + PipelineCacheRD pipeline; + } cube_to_dp; + + // Cubemap effects + + struct CubemapDownsamplerPushConstant { + uint32_t face_size; + uint32_t face_id; + float pad[2]; + }; + + struct CubemapDownsampler { + CubemapDownsamplerPushConstant push_constant; + CubemapDownsamplerShaderRD compute_shader; + CubemapDownsamplerRasterShaderRD raster_shader; + RID shader_version; + RID compute_pipeline; + PipelineCacheRD raster_pipeline; + } cubemap_downsampler; + + enum CubemapFilterMode { + FILTER_MODE_HIGH_QUALITY, + FILTER_MODE_LOW_QUALITY, + FILTER_MODE_HIGH_QUALITY_ARRAY, + FILTER_MODE_LOW_QUALITY_ARRAY, + FILTER_MODE_MAX, + }; + + struct CubemapFilterRasterPushConstant { + uint32_t mip_level; + uint32_t face_id; + float pad[2]; + }; + + struct CubemapFilter { + CubemapFilterShaderRD compute_shader; + CubemapFilterRasterShaderRD raster_shader; + RID shader_version; + RID compute_pipelines[FILTER_MODE_MAX]; + PipelineCacheRD raster_pipelines[FILTER_MODE_MAX]; + + RID uniform_set; + RID image_uniform_set; + RID coefficient_buffer; + bool use_high_quality; + + } filter; + + struct CubemapRoughnessPushConstant { + uint32_t face_id; + uint32_t sample_count; + float roughness; + uint32_t use_direct_write; + float face_size; + float pad[3]; + }; + + struct CubemapRoughness { + CubemapRoughnessPushConstant push_constant; + CubemapRoughnessShaderRD compute_shader; + CubemapRoughnessRasterShaderRD raster_shader; + RID shader_version; + RID compute_pipeline; + PipelineCacheRD raster_pipeline; + } roughness; + static CopyEffects *singleton; public: @@ -197,6 +282,8 @@ public: CopyEffects(bool p_prefer_raster_effects); ~CopyEffects(); + bool get_prefer_raster_effects() { return prefer_raster_effects; } + void copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_all_source = false, bool p_8_bit_dst = false, bool p_alpha_to_one = false); void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array); void copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false); @@ -213,6 +300,15 @@ public: void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size); void set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst = false); + + void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip); + void cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size); + void cubemap_downsample_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, const Size2i &p_size); + void cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array); + void cubemap_filter_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_mip_level); + + void cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size); + void cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size); }; } // namespace RendererRD diff --git a/servers/rendering/renderer_rd/effects/resolve.cpp b/servers/rendering/renderer_rd/effects/resolve.cpp new file mode 100644 index 0000000000..6c49a2ebce --- /dev/null +++ b/servers/rendering/renderer_rd/effects/resolve.cpp @@ -0,0 +1,130 @@ +/*************************************************************************/ +/* resolve.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "resolve.h" +#include "servers/rendering/renderer_rd/renderer_compositor_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" +#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h" + +using namespace RendererRD; + +Resolve::Resolve() { + Vector<String> resolve_modes; + resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n"); + resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n#define VOXEL_GI_RESOLVE\n"); + resolve_modes.push_back("\n#define MODE_RESOLVE_DEPTH\n"); + + resolve.shader.initialize(resolve_modes); + + resolve.shader_version = resolve.shader.version_create(); + + for (int i = 0; i < RESOLVE_MODE_MAX; i++) { + resolve.pipelines[i] = RD::get_singleton()->compute_pipeline_create(resolve.shader.version_get_shader(resolve.shader_version, i)); + } +} + +Resolve::~Resolve() { + resolve.shader.version_free(resolve.shader_version); +} + +void Resolve::resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples, uint32_t p_barrier) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + ResolvePushConstant push_constant; + push_constant.screen_size[0] = p_screen_size.x; + push_constant.screen_size[1] = p_screen_size.y; + push_constant.samples = p_samples; + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_depth })); + RD::Uniform u_source_normal_roughness(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, Vector<RID>({ default_sampler, p_source_normal_roughness })); + RD::Uniform u_dest_depth(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_dest_depth })); + RD::Uniform u_dest_normal_roughness(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_dest_normal_roughness })); + + ResolveMode mode = p_source_voxel_gi.is_valid() ? RESOLVE_MODE_GI_VOXEL_GI : RESOLVE_MODE_GI; + RID shader = resolve.shader.version_get_shader(resolve.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, resolve.pipelines[mode]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_depth, u_source_normal_roughness), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_dest_depth, u_dest_normal_roughness), 1); + if (p_source_voxel_gi.is_valid()) { + RD::Uniform u_source_voxel_gi(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_voxel_gi })); + RD::Uniform u_dest_voxel_gi(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_voxel_gi); + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_source_voxel_gi), 2); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_voxel_gi), 3); + } + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ResolvePushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.x, p_screen_size.y, 1); + + RD::get_singleton()->compute_list_end(p_barrier); +} + +void Resolve::resolve_depth(RID p_source_depth, RID p_dest_depth, Vector2i p_screen_size, int p_samples, uint32_t p_barrier) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + ResolvePushConstant push_constant; + push_constant.screen_size[0] = p_screen_size.x; + push_constant.screen_size[1] = p_screen_size.y; + push_constant.samples = p_samples; + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_depth })); + RD::Uniform u_dest_depth(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_depth); + + ResolveMode mode = RESOLVE_MODE_DEPTH; + RID shader = resolve.shader.version_get_shader(resolve.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, resolve.pipelines[mode]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_depth), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_dest_depth), 1); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ResolvePushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.x, p_screen_size.y, 1); + + RD::get_singleton()->compute_list_end(p_barrier); +} diff --git a/servers/rendering/renderer_rd/effects/resolve.h b/servers/rendering/renderer_rd/effects/resolve.h new file mode 100644 index 0000000000..d4b24a610f --- /dev/null +++ b/servers/rendering/renderer_rd/effects/resolve.h @@ -0,0 +1,74 @@ +/*************************************************************************/ +/* resolve.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RESOLVE_RD_H +#define RESOLVE_RD_H + +#include "servers/rendering/renderer_rd/pipeline_cache_rd.h" +#include "servers/rendering/renderer_rd/shaders/effects/resolve.glsl.gen.h" +#include "servers/rendering/renderer_scene_render.h" + +#include "servers/rendering_server.h" + +namespace RendererRD { + +class Resolve { +private: + struct ResolvePushConstant { + int32_t screen_size[2]; + int32_t samples; + uint32_t pad; + }; + + enum ResolveMode { + RESOLVE_MODE_GI, + RESOLVE_MODE_GI_VOXEL_GI, + RESOLVE_MODE_DEPTH, + RESOLVE_MODE_MAX + }; + + struct ResolveShader { + ResolvePushConstant push_constant; + ResolveShaderRD shader; + RID shader_version; + RID pipelines[RESOLVE_MODE_MAX]; //3 quality levels + } resolve; + +public: + Resolve(); + ~Resolve(); + + void resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL); + void resolve_depth(RID p_source_depth, RID p_dest_depth, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL); +}; + +} // namespace RendererRD + +#endif // !RESOLVE_RD_H diff --git a/servers/rendering/renderer_rd/effects/vrs.cpp b/servers/rendering/renderer_rd/effects/vrs.cpp new file mode 100644 index 0000000000..505a35a269 --- /dev/null +++ b/servers/rendering/renderer_rd/effects/vrs.cpp @@ -0,0 +1,171 @@ +/*************************************************************************/ +/* vrs.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "vrs.h" +#include "../renderer_compositor_rd.h" +#include "../storage_rd/texture_storage.h" +#include "../uniform_set_cache_rd.h" +#include "servers/xr_server.h" + +using namespace RendererRD; + +VRS::VRS() { + { + Vector<String> vrs_modes; + vrs_modes.push_back("\n"); // VRS_DEFAULT + vrs_modes.push_back("\n#define MULTIVIEW\n"); // VRS_MULTIVIEW + + vrs_shader.shader.initialize(vrs_modes); + + if (!RendererCompositorRD::singleton->is_xr_enabled()) { + vrs_shader.shader.set_variant_enabled(VRS_MULTIVIEW, false); + } + + vrs_shader.shader_version = vrs_shader.shader.version_create(); + + //use additive + + for (int i = 0; i < VRS_MAX; i++) { + if (vrs_shader.shader.is_variant_enabled(i)) { + vrs_shader.pipelines[i].setup(vrs_shader.shader.version_get_shader(vrs_shader.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); + } else { + vrs_shader.pipelines[i].clear(); + } + } + } +} + +VRS::~VRS() { + vrs_shader.shader.version_free(vrs_shader.shader_version); +} + +void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multiview) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + MaterialStorage *material_storage = MaterialStorage::get_singleton(); + ERR_FAIL_NULL(material_storage); + + // setup our uniforms + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture })); + + VRSMode mode = p_multiview ? VRS_MULTIVIEW : VRS_DEFAULT; + + RID shader = vrs_shader.shader.version_get_shader(vrs_shader.shader_version, mode); + ERR_FAIL_COND(shader.is_null()); + + 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_end(); +} + +void VRS::create_vrs_texture(const int p_base_width, const int p_base_height, const uint32_t p_view_count, RID &p_vrs_texture, RID &p_vrs_fb) { + // TODO find a way to skip this if VRS is not supported, but we don't have access to VulkanContext here, even though we're in vulkan.. hmmm + + // TODO we should find some way to store this properly, we're assuming 16x16 as this seems to be the standard but in our vrs_capacities we + // obtain a minimum and maximum size, and we should choose something within this range and then make sure that is consistantly set when creating + // our frame buffer. Also it is important that we make the resulting size we calculate down below available to the end user so they know the size + // of the VRS buffer to supply. + Size2i texel_size = Size2i(16, 16); + + RD::TextureFormat tf; + if (p_view_count > 1) { + tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + } else { + tf.texture_type = RD::TEXTURE_TYPE_2D; + } + tf.format = RD::DATA_FORMAT_R8_UINT; + tf.width = p_base_width / texel_size.x; + if (p_base_width % texel_size.x != 0) { + tf.width++; + } + tf.height = p_base_height / texel_size.y; + if (p_base_height % texel_size.y != 0) { + tf.height++; + } + tf.array_layers = p_view_count; // create a layer for every view + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + tf.samples = RD::TEXTURE_SAMPLES_1; + + p_vrs_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + // by default VRS is assumed to be our VRS attachment, but if we need to write into it, we need a bit more control + Vector<RID> fb; + fb.push_back(p_vrs_texture); + + RD::FramebufferPass pass; + pass.color_attachments.push_back(0); + + Vector<RD::FramebufferPass> passes; + passes.push_back(pass); + + p_vrs_fb = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, p_view_count); +} + +void VRS::update_vrs_texture(RID p_vrs_fb, RID p_render_target) { + TextureStorage *texture_storage = TextureStorage::get_singleton(); + RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(p_render_target); + + if (vrs_mode != RS::VIEWPORT_VRS_DISABLED) { + RD::get_singleton()->draw_command_begin_label("VRS Setup"); + + // TODO figure out if image has changed since it was last copied so we can save some resources.. + + if (vrs_mode == RS::VIEWPORT_VRS_TEXTURE) { + RID vrs_texture = texture_storage->render_target_get_vrs_texture(p_render_target); + if (vrs_texture.is_valid()) { + Texture *texture = texture_storage->get_texture(vrs_texture); + if (texture) { + // Copy into our density buffer + copy_vrs(texture->rd_texture, p_vrs_fb, texture->layers > 1); + } + } + } else if (vrs_mode == RS::VIEWPORT_VRS_XR) { + Ref<XRInterface> interface = XRServer::get_singleton()->get_primary_interface(); + if (interface.is_valid()) { + RID vrs_texture = interface->get_vrs_texture(); + if (vrs_texture.is_valid()) { + Texture *texture = texture_storage->get_texture(vrs_texture); + if (texture) { + // Copy into our density buffer + copy_vrs(texture->rd_texture, p_vrs_fb, texture->layers > 1); + } + } + } + } + + RD::get_singleton()->draw_command_end_label(); + } +} diff --git a/servers/rendering/renderer_rd/effects/vrs.h b/servers/rendering/renderer_rd/effects/vrs.h new file mode 100644 index 0000000000..0f2bdd31b6 --- /dev/null +++ b/servers/rendering/renderer_rd/effects/vrs.h @@ -0,0 +1,75 @@ +/*************************************************************************/ +/* vrs.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef VRS_RD_H +#define VRS_RD_H + +#include "servers/rendering/renderer_rd/pipeline_cache_rd.h" +#include "servers/rendering/renderer_rd/shaders/effects/vrs.glsl.gen.h" +#include "servers/rendering/renderer_scene_render.h" + +#include "servers/rendering_server.h" + +namespace RendererRD { + +class VRS { +private: + enum VRSMode { + VRS_DEFAULT, + VRS_MULTIVIEW, + VRS_MAX, + }; + + /* we have no push constant here (yet) + struct VRSPushConstant { + + }; + */ + + struct VRSShader { + // VRSPushConstant push_constant; + VrsShaderRD shader; + RID shader_version; + PipelineCacheRD pipelines[VRS_MAX]; + } vrs_shader; + +public: + VRS(); + ~VRS(); + + void copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multiview = false); + + void create_vrs_texture(const int p_base_width, const int p_base_height, const uint32_t p_view_count, RID &p_vrs_texture, RID &p_vrs_fb); + void update_vrs_texture(RID p_vrs_fb, RID p_render_target); +}; + +} // namespace RendererRD + +#endif // !VRS_RD_H diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp index 774745abdc..f731a0007a 100644 --- a/servers/rendering/renderer_rd/effects_rd.cpp +++ b/servers/rendering/renderer_rd/effects_rd.cpp @@ -86,7 +86,7 @@ RID EffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) u.append_id(p_texture); uniforms.push_back(u); // anything with the same configuration (one texture in binding 0 for set 0), is good - RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, cube_to_dp.shader.version_get_shader(cube_to_dp.shader_version, 0), 0); + RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, specular_merge.shader.version_get_shader(specular_merge.shader_version, 0), 0); texture_to_uniform_set_cache[p_texture] = uniform_set; @@ -252,6 +252,35 @@ void EffectsRD::fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RI RD::get_singleton()->compute_list_end(compute_list); } +void EffectsRD::taa_resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_prev_velocity, RID p_history, Size2 p_resolution, float p_z_near, float p_z_far) { + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + ERR_FAIL_NULL(uniform_set_cache); + + RID shader = TAA_resolve.shader.version_get_shader(TAA_resolve.shader_version, 0); + ERR_FAIL_COND(shader.is_null()); + + memset(&TAA_resolve.push_constant, 0, sizeof(TAAResolvePushConstant)); + TAA_resolve.push_constant.resolution_width = p_resolution.width; + TAA_resolve.push_constant.resolution_height = p_resolution.height; + TAA_resolve.push_constant.disocclusion_threshold = 0.025f; + TAA_resolve.push_constant.disocclusion_scale = 10.0f; + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, TAA_resolve.pipeline); + + RD::Uniform u_frame_source(RD::UNIFORM_TYPE_IMAGE, 0, { p_frame }); + RD::Uniform u_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, { default_sampler, p_depth }); + RD::Uniform u_velocity(RD::UNIFORM_TYPE_IMAGE, 2, { p_velocity }); + RD::Uniform u_prev_velocity(RD::UNIFORM_TYPE_IMAGE, 3, { p_prev_velocity }); + RD::Uniform u_history(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 4, { default_sampler, p_history }); + RD::Uniform u_frame_dest(RD::UNIFORM_TYPE_IMAGE, 5, { p_temp }); + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_frame_source, u_depth, u_velocity, u_prev_velocity, u_history, u_frame_dest), 0); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &TAA_resolve.push_constant, sizeof(TAAResolvePushConstant)); + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_resolution.width, p_resolution.height, 1); + RD::get_singleton()->compute_list_end(); +} + void EffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera) { RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); @@ -415,7 +444,7 @@ void EffectsRD::sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_dept } void EffectsRD::merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection) { - 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::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_READ, Vector<Color>()); if (p_reflection.is_valid()) { if (p_base.is_valid()) { @@ -444,28 +473,6 @@ void EffectsRD::merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_bas RD::get_singleton()->draw_list_end(); } -void EffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip) { - CopyToDPPushConstant push_constant; - push_constant.screen_rect[0] = p_rect.position.x; - push_constant.screen_rect[1] = p_rect.position.y; - push_constant.screen_rect[2] = p_rect.size.width; - push_constant.screen_rect[3] = p_rect.size.height; - push_constant.z_far = p_z_far; - push_constant.z_near = p_z_near; - push_constant.texel_size[0] = 1.0f / p_dst_size.x; - push_constant.texel_size[1] = 1.0f / p_dst_size.y; - push_constant.texel_size[0] *= p_dp_flip ? -1.0f : 1.0f; // Encode dp flip as x size sign - - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, cube_to_dp.pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - - RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(CopyToDPPushConstant)); - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_TRANSFER); -} - void EffectsRD::luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set) { ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of luminance reduction with the mobile renderer."); @@ -1224,189 +1231,6 @@ void EffectsRD::roughness_limit(RID p_source_normal, RID p_roughness, const Size RD::get_singleton()->compute_list_end(); } -void EffectsRD::cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size) { - ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute based cubemap roughness with the mobile renderer."); - - memset(&roughness.push_constant, 0, sizeof(CubemapRoughnessPushConstant)); - - roughness.push_constant.face_id = p_face_id > 9 ? 0 : p_face_id; - roughness.push_constant.roughness = p_roughness * p_roughness; // Shader expects roughness, not perceptual roughness, so multiply before passing in. - roughness.push_constant.sample_count = p_sample_count; - roughness.push_constant.use_direct_write = p_roughness == 0.0; - roughness.push_constant.face_size = p_size; - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, roughness.compute_pipeline); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture, true), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 1); - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &roughness.push_constant, sizeof(CubemapRoughnessPushConstant)); - - int x_groups = (p_size - 1) / 8 + 1; - int y_groups = (p_size - 1) / 8 + 1; - - RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, p_face_id > 9 ? 6 : 1); - - RD::get_singleton()->compute_list_end(); -} - -void EffectsRD::cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size) { - ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use raster based cubemap roughness with the clustered renderer."); - ERR_FAIL_COND_MSG(p_face_id >= 6, "Raster implementation of cubemap roughness must process one side at a time."); - - memset(&roughness.push_constant, 0, sizeof(CubemapRoughnessPushConstant)); - - roughness.push_constant.face_id = p_face_id; - roughness.push_constant.roughness = p_roughness * p_roughness; // Shader expects roughness, not perceptual roughness, so multiply before passing in. - roughness.push_constant.sample_count = p_sample_count; - roughness.push_constant.use_direct_write = p_roughness == 0.0; - roughness.push_constant.face_size = p_size; - - 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, _get_uniform_set_from_texture(p_source_rd_texture), 0); - RD::get_singleton()->draw_list_bind_index_array(draw_list, 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_end(); -} - -void EffectsRD::cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size) { - ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute based cubemap downsample with the mobile renderer."); - - cubemap_downsampler.push_constant.face_size = p_size.x; - cubemap_downsampler.push_constant.face_id = 0; // we render all 6 sides to each layer in one call - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, cubemap_downsampler.compute_pipeline); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_cubemap), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_cubemap), 1); - - int x_groups = (p_size.x - 1) / 8 + 1; - int y_groups = (p_size.y - 1) / 8 + 1; - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &cubemap_downsampler.push_constant, sizeof(CubemapDownsamplerPushConstant)); - - RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 6); // one z_group for each face - - RD::get_singleton()->compute_list_end(); -} - -void EffectsRD::cubemap_downsample_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, const Size2i &p_size) { - ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use raster based cubemap downsample with the clustered renderer."); - ERR_FAIL_COND_MSG(p_face_id >= 6, "Raster implementation of cubemap downsample must process one side at a time."); - - cubemap_downsampler.push_constant.face_size = p_size.x; - cubemap_downsampler.push_constant.face_id = p_face_id; - - 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, _get_uniform_set_from_texture(p_source_cubemap), 0); - RD::get_singleton()->draw_list_bind_index_array(draw_list, 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_end(); -} - -void EffectsRD::cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array) { - ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute based cubemap filter with the mobile renderer."); - - Vector<RD::Uniform> uniforms; - for (int i = 0; i < p_dest_cubemap.size(); i++) { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = i; - u.append_id(p_dest_cubemap[i]); - uniforms.push_back(u); - } - if (RD::get_singleton()->uniform_set_is_valid(filter.image_uniform_set)) { - RD::get_singleton()->free(filter.image_uniform_set); - } - filter.image_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.compute_shader.version_get_shader(filter.shader_version, 0), 2); - - int pipeline = p_use_array ? FILTER_MODE_HIGH_QUALITY_ARRAY : FILTER_MODE_HIGH_QUALITY; - pipeline = filter.use_high_quality ? pipeline : pipeline + 1; - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, filter.compute_pipelines[pipeline]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_cubemap, true), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, filter.uniform_set, 1); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, filter.image_uniform_set, 2); - - int x_groups = p_use_array ? 1792 : 342; // (128 * 128 * 7) / 64 : (128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2) / 64 - - RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, 6, 1); // one y_group for each face - - RD::get_singleton()->compute_list_end(); -} - -void EffectsRD::cubemap_filter_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_mip_level) { - ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use raster based cubemap filter with the clustered renderer."); - ERR_FAIL_COND_MSG(p_face_id >= 6, "Raster implementation of cubemap filter must process one side at a time."); - - // TODO implement! - CubemapFilterRasterPushConstant push_constant; - push_constant.mip_level = p_mip_level; - push_constant.face_id = p_face_id; - - CubemapFilterMode mode = filter.use_high_quality ? FILTER_MODE_HIGH_QUALITY : FILTER_MODE_LOW_QUALITY; - - 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, 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, _get_uniform_set_from_texture(p_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, 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_end(); -} - -void EffectsRD::resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples, uint32_t p_barrier) { - ResolvePushConstant push_constant; - push_constant.screen_size[0] = p_screen_size.x; - push_constant.screen_size[1] = p_screen_size.y; - push_constant.samples = p_samples; - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, resolve.pipelines[p_source_voxel_gi.is_valid() ? RESOLVE_MODE_GI_VOXEL_GI : RESOLVE_MODE_GI]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_pair(p_source_depth, p_source_normal_roughness), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_dest_depth, p_dest_normal_roughness), 1); - if (p_source_voxel_gi.is_valid()) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_voxel_gi), 2); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_voxel_gi), 3); - } - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ResolvePushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.x, p_screen_size.y, 1); - - RD::get_singleton()->compute_list_end(p_barrier); -} - -void EffectsRD::resolve_depth(RID p_source_depth, RID p_dest_depth, Vector2i p_screen_size, int p_samples, uint32_t p_barrier) { - ResolvePushConstant push_constant; - push_constant.screen_size[0] = p_screen_size.x; - push_constant.screen_size[1] = p_screen_size.y; - push_constant.samples = p_samples; - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, resolve.pipelines[RESOLVE_MODE_DEPTH]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_depth), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_depth), 1); - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ResolvePushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.x, p_screen_size.y, 1); - - RD::get_singleton()->compute_list_end(p_barrier); -} - void EffectsRD::sort_buffer(RID p_uniform_set, int p_size) { Sort::PushConstant push_constant; push_constant.total_elements = p_size; @@ -1485,7 +1309,7 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n"); #else // Everyone else can use normal mode when available. - if (RD::get_singleton()->get_device_capabilities()->supports_fsr_half_float) { + if (RD::get_singleton()->has_feature(RD::SUPPORTS_FSR_HALF_FLOAT)) { FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_NORMAL\n"); } else { FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n"); @@ -1500,28 +1324,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { prefer_raster_effects = p_prefer_raster_effects; - { - // Initialize roughness - Vector<String> cubemap_roughness_modes; - cubemap_roughness_modes.push_back(""); - - if (prefer_raster_effects) { - roughness.raster_shader.initialize(cubemap_roughness_modes); - - roughness.shader_version = roughness.raster_shader.version_create(); - - roughness.raster_pipeline.setup(roughness.raster_shader.version_get_shader(roughness.shader_version, 0), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); - - } else { - roughness.compute_shader.initialize(cubemap_roughness_modes); - - roughness.shader_version = roughness.compute_shader.version_create(); - - roughness.compute_pipeline = RD::get_singleton()->compute_pipeline_create(roughness.compute_shader.version_get_shader(roughness.shader_version, 0)); - roughness.raster_pipeline.clear(); - } - } - if (prefer_raster_effects) { Vector<String> luminance_reduce_modes; luminance_reduce_modes.push_back("\n#define FIRST_PASS\n"); // LUMINANCE_REDUCE_FRAGMENT_FIRST @@ -1555,22 +1357,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { } } - { - // Initialize copier - Vector<String> copy_modes; - copy_modes.push_back("\n"); - - cube_to_dp.shader.initialize(copy_modes); - - cube_to_dp.shader_version = cube_to_dp.shader.version_create(); - RID shader = cube_to_dp.shader.version_get_shader(cube_to_dp.shader_version, 0); - RD::PipelineDepthStencilState dss; - dss.enable_depth_test = true; - dss.depth_compare_operator = RD::COMPARE_OP_ALWAYS; - dss.enable_depth_write = true; - cube_to_dp.pipeline.setup(shader, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), dss, RD::PipelineColorBlendState(), 0); - } - if (!prefer_raster_effects) { { // Initialize depth buffer for screen space effects @@ -1731,92 +1517,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { roughness_limiter.pipeline = RD::get_singleton()->compute_pipeline_create(roughness_limiter.shader.version_get_shader(roughness_limiter.shader_version, 0)); } - { - //Initialize cubemap downsampler - Vector<String> cubemap_downsampler_modes; - cubemap_downsampler_modes.push_back(""); - - if (prefer_raster_effects) { - cubemap_downsampler.raster_shader.initialize(cubemap_downsampler_modes); - - cubemap_downsampler.shader_version = cubemap_downsampler.raster_shader.version_create(); - - cubemap_downsampler.raster_pipeline.setup(cubemap_downsampler.raster_shader.version_get_shader(cubemap_downsampler.shader_version, 0), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); - } else { - cubemap_downsampler.compute_shader.initialize(cubemap_downsampler_modes); - - cubemap_downsampler.shader_version = cubemap_downsampler.compute_shader.version_create(); - - cubemap_downsampler.compute_pipeline = RD::get_singleton()->compute_pipeline_create(cubemap_downsampler.compute_shader.version_get_shader(cubemap_downsampler.shader_version, 0)); - cubemap_downsampler.raster_pipeline.clear(); - } - } - - { - // Initialize cubemap filter - filter.use_high_quality = GLOBAL_GET("rendering/reflections/sky_reflections/fast_filter_high_quality"); - - Vector<String> cubemap_filter_modes; - cubemap_filter_modes.push_back("\n#define USE_HIGH_QUALITY\n"); - cubemap_filter_modes.push_back("\n#define USE_LOW_QUALITY\n"); - cubemap_filter_modes.push_back("\n#define USE_HIGH_QUALITY\n#define USE_TEXTURE_ARRAY\n"); - cubemap_filter_modes.push_back("\n#define USE_LOW_QUALITY\n#define USE_TEXTURE_ARRAY\n"); - - if (filter.use_high_quality) { - filter.coefficient_buffer = RD::get_singleton()->storage_buffer_create(sizeof(high_quality_coeffs)); - RD::get_singleton()->buffer_update(filter.coefficient_buffer, 0, sizeof(high_quality_coeffs), &high_quality_coeffs[0]); - } else { - filter.coefficient_buffer = RD::get_singleton()->storage_buffer_create(sizeof(low_quality_coeffs)); - RD::get_singleton()->buffer_update(filter.coefficient_buffer, 0, sizeof(low_quality_coeffs), &low_quality_coeffs[0]); - } - - if (prefer_raster_effects) { - filter.raster_shader.initialize(cubemap_filter_modes); - - // array variants are not supported in raster - filter.raster_shader.set_variant_enabled(FILTER_MODE_HIGH_QUALITY_ARRAY, false); - filter.raster_shader.set_variant_enabled(FILTER_MODE_LOW_QUALITY_ARRAY, false); - - filter.shader_version = filter.raster_shader.version_create(); - - for (int i = 0; i < FILTER_MODE_MAX; i++) { - if (filter.raster_shader.is_variant_enabled(i)) { - filter.raster_pipelines[i].setup(filter.raster_shader.version_get_shader(filter.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); - } else { - filter.raster_pipelines[i].clear(); - } - } - - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 0; - u.append_id(filter.coefficient_buffer); - uniforms.push_back(u); - } - filter.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.raster_shader.version_get_shader(filter.shader_version, filter.use_high_quality ? 0 : 1), 1); - } else { - filter.compute_shader.initialize(cubemap_filter_modes); - filter.shader_version = filter.compute_shader.version_create(); - - for (int i = 0; i < FILTER_MODE_MAX; i++) { - filter.compute_pipelines[i] = RD::get_singleton()->compute_pipeline_create(filter.compute_shader.version_get_shader(filter.shader_version, i)); - filter.raster_pipelines[i].clear(); - } - - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 0; - u.append_id(filter.coefficient_buffer); - uniforms.push_back(u); - } - filter.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.compute_shader.version_get_shader(filter.shader_version, filter.use_high_quality ? 0 : 1), 1); - } - } - if (!prefer_raster_effects) { Vector<String> specular_modes; specular_modes.push_back("\n#define MODE_MERGE\n"); @@ -1980,21 +1680,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.interleave_shader.version_get_shader(ssil.interleave_shader_version, i - SSIL_INTERLEAVE)); } } - - { - Vector<String> resolve_modes; - resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n"); - resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n#define VOXEL_GI_RESOLVE\n"); - resolve_modes.push_back("\n#define MODE_RESOLVE_DEPTH\n"); - - resolve.shader.initialize(resolve_modes); - - resolve.shader_version = resolve.shader.version_create(); - - for (int i = 0; i < RESOLVE_MODE_MAX; i++) { - resolve.pipelines[i] = RD::get_singleton()->compute_pipeline_create(resolve.shader.version_get_shader(resolve.shader_version, i)); - } - } } { @@ -2012,6 +1697,14 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { } } + { + Vector<String> taa_modes; + taa_modes.push_back("\n#define MODE_TAA_RESOLVE"); + TAA_resolve.shader.initialize(taa_modes); + TAA_resolve.shader_version = TAA_resolve.shader.version_create(); + TAA_resolve.pipeline = RD::get_singleton()->compute_pipeline_create(TAA_resolve.shader.version_get_shader(TAA_resolve.shader_version, 0)); + } + RD::SamplerState sampler; sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR; sampler.min_filter = RD::SAMPLER_FILTER_LINEAR; @@ -2046,33 +1739,18 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) { } EffectsRD::~EffectsRD() { - if (RD::get_singleton()->uniform_set_is_valid(filter.image_uniform_set)) { - RD::get_singleton()->free(filter.image_uniform_set); - } - - if (RD::get_singleton()->uniform_set_is_valid(filter.uniform_set)) { - RD::get_singleton()->free(filter.uniform_set); - } - RD::get_singleton()->free(default_sampler); RD::get_singleton()->free(default_mipmap_sampler); RD::get_singleton()->free(index_buffer); //array gets freed as dependency - RD::get_singleton()->free(filter.coefficient_buffer); FSR_upscale.shader.version_free(FSR_upscale.shader_version); + TAA_resolve.shader.version_free(TAA_resolve.shader_version); if (prefer_raster_effects) { luminance_reduce_raster.shader.version_free(luminance_reduce_raster.shader_version); - roughness.raster_shader.version_free(roughness.shader_version); - cubemap_downsampler.raster_shader.version_free(cubemap_downsampler.shader_version); - filter.raster_shader.version_free(filter.shader_version); } else { luminance_reduce.shader.version_free(luminance_reduce.shader_version); - roughness.compute_shader.version_free(roughness.shader_version); - cubemap_downsampler.compute_shader.version_free(cubemap_downsampler.shader_version); - filter.compute_shader.version_free(filter.shader_version); } if (!prefer_raster_effects) { - resolve.shader.version_free(resolve.shader_version); specular_merge.shader.version_free(specular_merge.shader_version); ss_effects.downsample_shader.version_free(ss_effects.downsample_shader_version); ssao.blur_shader.version_free(ssao.blur_shader_version); @@ -2095,6 +1773,5 @@ EffectsRD::~EffectsRD() { RD::get_singleton()->free(ssil.importance_map_load_counter); RD::get_singleton()->free(ssil.projection_uniform_buffer); } - cube_to_dp.shader.version_free(cube_to_dp.shader_version); sort.shader.version_free(sort.shader_version); } diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h index 4774864824..76627a8d7d 100644 --- a/servers/rendering/renderer_rd/effects_rd.h +++ b/servers/rendering/renderer_rd/effects_rd.h @@ -33,17 +33,9 @@ #include "core/math/camera_matrix.h" #include "servers/rendering/renderer_rd/pipeline_cache_rd.h" -#include "servers/rendering/renderer_rd/shaders/cube_to_dp.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/cubemap_downsampler.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/cubemap_downsampler_raster.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/cubemap_filter.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/cubemap_filter_raster.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/cubemap_roughness_raster.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/fsr_upscale.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/luminance_reduce.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/resolve.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/roughness_limiter.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl.gen.h" @@ -60,6 +52,7 @@ #include "servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/ssil_interleave.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/taa_resolve.glsl.gen.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering_server.h" @@ -90,23 +83,19 @@ private: RID pipeline; } FSR_upscale; - struct CubemapRoughnessPushConstant { - uint32_t face_id; - uint32_t sample_count; - float roughness; - uint32_t use_direct_write; - float face_size; - float pad[3]; + struct TAAResolvePushConstant { + float resolution_width; + float resolution_height; + float disocclusion_threshold; + float disocclusion_scale; }; - struct CubemapRoughness { - CubemapRoughnessPushConstant push_constant; - CubemapRoughnessShaderRD compute_shader; - CubemapRoughnessRasterShaderRD raster_shader; + struct TAAResolve { + TAAResolvePushConstant push_constant; + TaaResolveShaderRD shader; RID shader_version; - RID compute_pipeline; - PipelineCacheRD raster_pipeline; - } roughness; + RID pipeline; + } TAA_resolve; enum LuminanceReduceMode { LUMINANCE_REDUCE_READ, @@ -153,19 +142,6 @@ private: PipelineCacheRD pipelines[LUMINANCE_REDUCE_FRAGMENT_MAX]; } luminance_reduce_raster; - struct CopyToDPPushConstant { - float z_far; - float z_near; - float texel_size[2]; - float screen_rect[4]; - }; - - struct CoptToDP { - CubeToDpShaderRD shader; - RID shader_version; - PipelineCacheRD pipeline; - } cube_to_dp; - struct SSEffectsDownsamplePushConstant { float pixel_size[2]; float z_far; @@ -405,49 +381,6 @@ private: } roughness_limiter; - struct CubemapDownsamplerPushConstant { - uint32_t face_size; - uint32_t face_id; - float pad[2]; - }; - - struct CubemapDownsampler { - CubemapDownsamplerPushConstant push_constant; - CubemapDownsamplerShaderRD compute_shader; - CubemapDownsamplerRasterShaderRD raster_shader; - RID shader_version; - RID compute_pipeline; - PipelineCacheRD raster_pipeline; - } cubemap_downsampler; - - enum CubemapFilterMode { - FILTER_MODE_HIGH_QUALITY, - FILTER_MODE_LOW_QUALITY, - FILTER_MODE_HIGH_QUALITY_ARRAY, - FILTER_MODE_LOW_QUALITY_ARRAY, - FILTER_MODE_MAX, - }; - - struct CubemapFilterRasterPushConstant { - uint32_t mip_level; - uint32_t face_id; - float pad[2]; - }; - - struct CubemapFilter { - CubemapFilterShaderRD compute_shader; - CubemapFilterRasterShaderRD raster_shader; - RID shader_version; - RID compute_pipelines[FILTER_MODE_MAX]; - PipelineCacheRD raster_pipelines[FILTER_MODE_MAX]; - - RID uniform_set; - RID image_uniform_set; - RID coefficient_buffer; - bool use_high_quality; - - } filter; - enum SpecularMergeMode { SPECULAR_MERGE_ADD, SPECULAR_MERGE_SSR, @@ -564,26 +497,6 @@ private: RID pipelines[3]; //3 quality levels } sss; - struct ResolvePushConstant { - int32_t screen_size[2]; - int32_t samples; - uint32_t pad; - }; - - enum ResolveMode { - RESOLVE_MODE_GI, - RESOLVE_MODE_GI_VOXEL_GI, - RESOLVE_MODE_DEPTH, - RESOLVE_MODE_MAX - }; - - struct Resolve { - ResolvePushConstant push_constant; - ResolveShaderRD shader; - RID shader_version; - RID pipelines[RESOLVE_MODE_MAX]; //3 quality levels - } resolve; - enum SortMode { SORT_MODE_BLOCK, SORT_MODE_STEP, @@ -608,10 +521,10 @@ private: RID index_buffer; RID index_array; - Map<RID, RID> texture_to_uniform_set_cache; - Map<RID, RID> input_to_uniform_set_cache; + HashMap<RID, RID> texture_to_uniform_set_cache; + HashMap<RID, RID> input_to_uniform_set_cache; - Map<RID, RID> image_to_uniform_set_cache; + HashMap<RID, RID> image_to_uniform_set_cache; struct TexturePair { RID texture1; @@ -637,11 +550,11 @@ private: } }; - Map<TexturePair, RID> texture_pair_to_uniform_set_cache; - Map<RID, RID> texture_to_compute_uniform_set_cache; - Map<TexturePair, RID> texture_pair_to_compute_uniform_set_cache; - Map<TexturePair, RID> image_pair_to_compute_uniform_set_cache; - Map<TextureSamplerPair, RID> texture_sampler_to_compute_uniform_set_cache; + RBMap<TexturePair, RID> texture_pair_to_uniform_set_cache; + RBMap<RID, RID> texture_to_compute_uniform_set_cache; + RBMap<TexturePair, RID> texture_pair_to_compute_uniform_set_cache; + RBMap<TexturePair, RID> image_pair_to_compute_uniform_set_cache; + RBMap<TextureSamplerPair, RID> texture_sampler_to_compute_uniform_set_cache; RID _get_uniform_set_from_image(RID p_texture); RID _get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false); @@ -654,10 +567,8 @@ public: bool get_prefer_raster_effects(); void fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness); + void taa_resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_prev_velocity, RID p_history, Size2 p_resolution, float p_z_near, float p_z_far); - void cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size); - void cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size); - void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip); void luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false); void luminance_reduction_raster(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, Vector<RID> p_fb, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false); @@ -708,18 +619,11 @@ public: void screen_space_indirect_lighting(RID p_diffuse, RID p_destination, RID p_normal_buffer, RID p_depth_mipmaps_texture, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_importance_map, RID p_importance_map_pong, RID p_edges, const Vector<RID> p_edges_slices, const CameraMatrix &p_projection, const CameraMatrix &p_last_projection, const SSILSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set, RID &r_projection_uniform_set); void roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve); - void cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size); - void cubemap_downsample_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, const Size2i &p_size); - void cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array); - void cubemap_filter_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_mip_level); void screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera); void merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection); void sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const CameraMatrix &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality); - void resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL); - void resolve_depth(RID p_source_depth, RID p_dest_depth, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL); - void sort_buffer(RID p_uniform_set, int p_size); EffectsRD(bool p_prefer_raster_effects); diff --git a/servers/rendering/renderer_rd/environment/SCsub b/servers/rendering/renderer_rd/environment/SCsub new file mode 100644 index 0000000000..86681f9c74 --- /dev/null +++ b/servers/rendering/renderer_rd/environment/SCsub @@ -0,0 +1,5 @@ +#!/usr/bin/env python + +Import("env") + +env.add_source_files(env.servers_sources, "*.cpp") diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp new file mode 100644 index 0000000000..2a6c96480e --- /dev/null +++ b/servers/rendering/renderer_rd/environment/fog.cpp @@ -0,0 +1,128 @@ +/*************************************************************************/ +/* fog.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "fog.h" + +using namespace RendererRD; + +Fog *Fog::singleton = nullptr; + +Fog::Fog() { + singleton = this; +} + +Fog::~Fog() { + singleton = nullptr; +} + +/* FOG VOLUMES */ + +RID Fog::fog_volume_allocate() { + return fog_volume_owner.allocate_rid(); +} + +void Fog::fog_volume_initialize(RID p_rid) { + fog_volume_owner.initialize_rid(p_rid, FogVolume()); +} + +void Fog::fog_free(RID p_rid) { + FogVolume *fog_volume = fog_volume_owner.get_or_null(p_rid); + fog_volume->dependency.deleted_notify(p_rid); + fog_volume_owner.free(p_rid); +} + +void Fog::fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) { + FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); + ERR_FAIL_COND(!fog_volume); + + if (p_shape == fog_volume->shape) { + return; + } + + fog_volume->shape = p_shape; + fog_volume->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); +} + +void Fog::fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) { + FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); + ERR_FAIL_COND(!fog_volume); + + fog_volume->extents = p_extents; + fog_volume->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); +} + +void Fog::fog_volume_set_material(RID p_fog_volume, RID p_material) { + FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); + ERR_FAIL_COND(!fog_volume); + fog_volume->material = p_material; +} + +RID Fog::fog_volume_get_material(RID p_fog_volume) const { + FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); + ERR_FAIL_COND_V(!fog_volume, RID()); + + return fog_volume->material; +} + +RS::FogVolumeShape Fog::fog_volume_get_shape(RID p_fog_volume) const { + FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); + ERR_FAIL_COND_V(!fog_volume, RS::FOG_VOLUME_SHAPE_BOX); + + return fog_volume->shape; +} + +AABB Fog::fog_volume_get_aabb(RID p_fog_volume) const { + FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); + ERR_FAIL_COND_V(!fog_volume, AABB()); + + switch (fog_volume->shape) { + case RS::FOG_VOLUME_SHAPE_ELLIPSOID: + case RS::FOG_VOLUME_SHAPE_CONE: + case RS::FOG_VOLUME_SHAPE_CYLINDER: + case RS::FOG_VOLUME_SHAPE_BOX: { + AABB aabb; + aabb.position = -fog_volume->extents; + aabb.size = fog_volume->extents * 2; + return aabb; + } + default: { + // Need some size otherwise will get culled + return AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2)); + } + } + + return AABB(); +} + +Vector3 Fog::fog_volume_get_extents(RID p_fog_volume) const { + const FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); + ERR_FAIL_COND_V(!fog_volume, Vector3()); + return fog_volume->extents; +} diff --git a/servers/rendering/renderer_rd/environment/fog.h b/servers/rendering/renderer_rd/environment/fog.h new file mode 100644 index 0000000000..55a01c3616 --- /dev/null +++ b/servers/rendering/renderer_rd/environment/fog.h @@ -0,0 +1,83 @@ +/*************************************************************************/ +/* fog.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef FOG_RD_H +#define FOG_RD_H + +#include "core/templates/local_vector.h" +#include "core/templates/rid_owner.h" +#include "servers/rendering/environment/renderer_fog.h" +#include "servers/rendering/storage/utilities.h" + +namespace RendererRD { + +class Fog : public RendererFog { +public: + struct FogVolume { + RID material; + Vector3 extents = Vector3(1, 1, 1); + + RS::FogVolumeShape shape = RS::FOG_VOLUME_SHAPE_BOX; + + Dependency dependency; + }; + +private: + static Fog *singleton; + + mutable RID_Owner<FogVolume, true> fog_volume_owner; + +public: + static Fog *get_singleton() { return singleton; } + + Fog(); + ~Fog(); + + /* FOG VOLUMES */ + + FogVolume *get_fog_volume(RID p_rid) { return fog_volume_owner.get_or_null(p_rid); }; + bool owns_fog_volume(RID p_rid) { return fog_volume_owner.owns(p_rid); }; + + virtual RID fog_volume_allocate() override; + virtual void fog_volume_initialize(RID p_rid) override; + virtual void fog_free(RID p_rid) override; + + virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override; + virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override; + virtual void fog_volume_set_material(RID p_fog_volume, RID p_material) override; + virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const override; + RID fog_volume_get_material(RID p_fog_volume) const; + virtual AABB fog_volume_get_aabb(RID p_fog_volume) const override; + Vector3 fog_volume_get_extents(RID p_fog_volume) const; +}; + +} // namespace RendererRD + +#endif // !FOG_RD_H diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/environment/gi.cpp index 7aede6bb48..3275aea13c 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp +++ b/servers/rendering/renderer_rd/environment/gi.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* renderer_scene_gi_rd.cpp */ +/* gi.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,24 +28,356 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "renderer_scene_gi_rd.h" +#include "gi.h" #include "core/config/project_settings.h" +#include "servers/rendering/renderer_rd/renderer_compositor_rd.h" #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" #include "servers/rendering/renderer_rd/storage_rd/material_storage.h" #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/rendering_server_default.h" -const Vector3i RendererSceneGIRD::SDFGI::Cascade::DIRTY_ALL = Vector3i(0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF); +using namespace RendererRD; + +const Vector3i GI::SDFGI::Cascade::DIRTY_ALL = Vector3i(0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF); + +GI *GI::singleton = nullptr; + +//////////////////////////////////////////////////////////////////////////////// +// VOXEL GI STORAGE + +RID GI::voxel_gi_allocate() { + return voxel_gi_owner.allocate_rid(); +} + +void GI::voxel_gi_free(RID p_voxel_gi) { + voxel_gi_allocate_data(p_voxel_gi, Transform3D(), AABB(), Vector3i(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<int>()); //deallocate + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + voxel_gi->dependency.deleted_notify(p_voxel_gi); + voxel_gi_owner.free(p_voxel_gi); +} + +void GI::voxel_gi_initialize(RID p_voxel_gi) { + voxel_gi_owner.initialize_rid(p_voxel_gi, VoxelGI()); +} + +void GI::voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND(!voxel_gi); + + if (voxel_gi->octree_buffer.is_valid()) { + RD::get_singleton()->free(voxel_gi->octree_buffer); + RD::get_singleton()->free(voxel_gi->data_buffer); + if (voxel_gi->sdf_texture.is_valid()) { + RD::get_singleton()->free(voxel_gi->sdf_texture); + } + + voxel_gi->sdf_texture = RID(); + voxel_gi->octree_buffer = RID(); + voxel_gi->data_buffer = RID(); + voxel_gi->octree_buffer_size = 0; + voxel_gi->data_buffer_size = 0; + voxel_gi->cell_count = 0; + } + + voxel_gi->to_cell_xform = p_to_cell_xform; + voxel_gi->bounds = p_aabb; + voxel_gi->octree_size = p_octree_size; + voxel_gi->level_counts = p_level_counts; + + if (p_octree_cells.size()) { + ERR_FAIL_COND(p_octree_cells.size() % 32 != 0); //cells size must be a multiple of 32 + + uint32_t cell_count = p_octree_cells.size() / 32; + + ERR_FAIL_COND(p_data_cells.size() != (int)cell_count * 16); //see that data size matches + + voxel_gi->cell_count = cell_count; + voxel_gi->octree_buffer = RD::get_singleton()->storage_buffer_create(p_octree_cells.size(), p_octree_cells); + voxel_gi->octree_buffer_size = p_octree_cells.size(); + voxel_gi->data_buffer = RD::get_singleton()->storage_buffer_create(p_data_cells.size(), p_data_cells); + voxel_gi->data_buffer_size = p_data_cells.size(); + + if (p_distance_field.size()) { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8_UNORM; + tf.width = voxel_gi->octree_size.x; + tf.height = voxel_gi->octree_size.y; + tf.depth = voxel_gi->octree_size.z; + tf.texture_type = RD::TEXTURE_TYPE_3D; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + Vector<Vector<uint8_t>> s; + s.push_back(p_distance_field); + voxel_gi->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView(), s); + RD::get_singleton()->set_resource_name(voxel_gi->sdf_texture, "VoxelGI SDF Texture"); + } +#if 0 + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8_UNORM; + tf.width = voxel_gi->octree_size.x; + tf.height = voxel_gi->octree_size.y; + tf.depth = voxel_gi->octree_size.z; + tf.type = RD::TEXTURE_TYPE_3D; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UNORM); + tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UINT); + voxel_gi->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(voxel_gi->sdf_texture, "VoxelGI SDF Texture"); + } + RID shared_tex; + { + RD::TextureView tv; + tv.format_override = RD::DATA_FORMAT_R8_UINT; + shared_tex = RD::get_singleton()->texture_create_shared(tv, voxel_gi->sdf_texture); + } + //update SDF texture + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 1; + u.append_id(voxel_gi->octree_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 2; + u.append_id(voxel_gi->data_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 3; + u.append_id(shared_tex); + uniforms.push_back(u); + } + + RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, voxel_gi_sdf_shader_version_shader, 0); + + { + uint32_t push_constant[4] = { 0, 0, 0, 0 }; + + for (int i = 0; i < voxel_gi->level_counts.size() - 1; i++) { + push_constant[0] += voxel_gi->level_counts[i]; + } + push_constant[1] = push_constant[0] + voxel_gi->level_counts[voxel_gi->level_counts.size() - 1]; + + print_line("offset: " + itos(push_constant[0])); + print_line("size: " + itos(push_constant[1])); + //create SDF + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, voxel_gi_sdf_shader_pipeline); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set, 0); + RD::get_singleton()->compute_list_set_push_constant(compute_list, push_constant, sizeof(uint32_t) * 4); + RD::get_singleton()->compute_list_dispatch(compute_list, voxel_gi->octree_size.x / 4, voxel_gi->octree_size.y / 4, voxel_gi->octree_size.z / 4); + RD::get_singleton()->compute_list_end(); + } + + RD::get_singleton()->free(uniform_set); + RD::get_singleton()->free(shared_tex); + } +#endif + } + + voxel_gi->version++; + voxel_gi->data_version++; + + voxel_gi->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); +} + +AABB GI::voxel_gi_get_bounds(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, AABB()); + + return voxel_gi->bounds; +} + +Vector3i GI::voxel_gi_get_octree_size(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, Vector3i()); + return voxel_gi->octree_size; +} + +Vector<uint8_t> GI::voxel_gi_get_octree_cells(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, Vector<uint8_t>()); + + if (voxel_gi->octree_buffer.is_valid()) { + return RD::get_singleton()->buffer_get_data(voxel_gi->octree_buffer); + } + return Vector<uint8_t>(); +} + +Vector<uint8_t> GI::voxel_gi_get_data_cells(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, Vector<uint8_t>()); + + if (voxel_gi->data_buffer.is_valid()) { + return RD::get_singleton()->buffer_get_data(voxel_gi->data_buffer); + } + return Vector<uint8_t>(); +} + +Vector<uint8_t> GI::voxel_gi_get_distance_field(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, Vector<uint8_t>()); + + if (voxel_gi->data_buffer.is_valid()) { + return RD::get_singleton()->texture_get_data(voxel_gi->sdf_texture, 0); + } + return Vector<uint8_t>(); +} + +Vector<int> GI::voxel_gi_get_level_counts(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, Vector<int>()); + + return voxel_gi->level_counts; +} + +Transform3D GI::voxel_gi_get_to_cell_xform(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, Transform3D()); + + return voxel_gi->to_cell_xform; +} + +void GI::voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND(!voxel_gi); + + voxel_gi->dynamic_range = p_range; + voxel_gi->version++; +} + +float GI::voxel_gi_get_dynamic_range(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, 0); + + return voxel_gi->dynamic_range; +} + +void GI::voxel_gi_set_propagation(RID p_voxel_gi, float p_range) { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND(!voxel_gi); + + voxel_gi->propagation = p_range; + voxel_gi->version++; +} + +float GI::voxel_gi_get_propagation(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, 0); + return voxel_gi->propagation; +} + +void GI::voxel_gi_set_energy(RID p_voxel_gi, float p_energy) { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND(!voxel_gi); + + voxel_gi->energy = p_energy; +} + +float GI::voxel_gi_get_energy(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, 0); + return voxel_gi->energy; +} + +void GI::voxel_gi_set_bias(RID p_voxel_gi, float p_bias) { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND(!voxel_gi); + + voxel_gi->bias = p_bias; +} + +float GI::voxel_gi_get_bias(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, 0); + return voxel_gi->bias; +} + +void GI::voxel_gi_set_normal_bias(RID p_voxel_gi, float p_normal_bias) { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND(!voxel_gi); + + voxel_gi->normal_bias = p_normal_bias; +} + +float GI::voxel_gi_get_normal_bias(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, 0); + return voxel_gi->normal_bias; +} + +void GI::voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND(!voxel_gi); + + voxel_gi->interior = p_enable; +} + +void GI::voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND(!voxel_gi); + + voxel_gi->use_two_bounces = p_enable; + voxel_gi->version++; +} + +bool GI::voxel_gi_is_using_two_bounces(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, false); + return voxel_gi->use_two_bounces; +} + +bool GI::voxel_gi_is_interior(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, 0); + return voxel_gi->interior; +} + +uint32_t GI::voxel_gi_get_version(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, 0); + return voxel_gi->version; +} + +uint32_t GI::voxel_gi_get_data_version(RID p_voxel_gi) { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, 0); + return voxel_gi->data_version; +} + +RID GI::voxel_gi_get_octree_buffer(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, RID()); + return voxel_gi->octree_buffer; +} + +RID GI::voxel_gi_get_data_buffer(RID p_voxel_gi) const { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, RID()); + return voxel_gi->data_buffer; +} + +RID GI::voxel_gi_get_sdf_texture(RID p_voxel_gi) { + VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); + ERR_FAIL_COND_V(!voxel_gi, RID()); + + return voxel_gi->sdf_texture; +} //////////////////////////////////////////////////////////////////////////////// // SDFGI -void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, RendererSceneGIRD *p_gi) { +void GI::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, GI *p_gi) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - storage = p_gi->storage; gi = p_gi; num_cascades = p_env->sdfgi_cascades; min_cell_size = p_env->sdfgi_min_cell_size; @@ -72,29 +404,38 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V RD::TextureFormat tf_render = tf_sdf; tf_render.format = RD::DATA_FORMAT_R16_UINT; render_albedo = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + RD::get_singleton()->set_resource_name(render_albedo, "VoxelGI Render Albedo"); tf_render.format = RD::DATA_FORMAT_R32_UINT; render_emission = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + RD::get_singleton()->set_resource_name(render_emission, "VoxelGI Render Emission"); render_emission_aniso = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + RD::get_singleton()->set_resource_name(render_emission_aniso, "VoxelGI Render Emission Aniso"); tf_render.format = RD::DATA_FORMAT_R8_UNORM; //at least its easy to visualize for (int i = 0; i < 8; i++) { render_occlusion[i] = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + RD::get_singleton()->set_resource_name(render_occlusion[i], String("VoxelGI Render Occlusion ") + itos(i)); } tf_render.format = RD::DATA_FORMAT_R32_UINT; render_geom_facing = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + RD::get_singleton()->set_resource_name(render_geom_facing, "VoxelGI Render Geometry Facing"); tf_render.format = RD::DATA_FORMAT_R8G8B8A8_UINT; render_sdf[0] = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + RD::get_singleton()->set_resource_name(render_sdf[0], "VoxelGI Render SDF 0"); render_sdf[1] = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + RD::get_singleton()->set_resource_name(render_sdf[1], "VoxelGI Render SDF 1"); tf_render.width /= 2; tf_render.height /= 2; tf_render.depth /= 2; render_sdf_half[0] = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + RD::get_singleton()->set_resource_name(render_sdf_half[0], "VoxelGI Render SDF Half 0"); render_sdf_half[1] = RD::get_singleton()->texture_create(tf_render, RD::TextureView()); + RD::get_singleton()->set_resource_name(render_sdf_half[1], "VoxelGI Render SDF Half 1"); } RD::TextureFormat tf_occlusion = tf_sdf; @@ -135,7 +476,9 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V tf_probe_average.texture_type = RD::TEXTURE_TYPE_2D; lightprobe_history_scroll = RD::get_singleton()->texture_create(tf_probe_history, RD::TextureView()); + RD::get_singleton()->set_resource_name(lightprobe_history_scroll, "VoxelGI LightProbe History Scroll"); lightprobe_average_scroll = RD::get_singleton()->texture_create(tf_probe_average, RD::TextureView()); + RD::get_singleton()->set_resource_name(lightprobe_average_scroll, "VoxelGI LightProbe Average Scroll"); { //octahedral lightprobes @@ -149,6 +492,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V //lightprobe texture is an octahedral texture lightprobe_data = RD::get_singleton()->texture_create(tf_octprobes, RD::TextureView()); + RD::get_singleton()->set_resource_name(lightprobe_data, "VoxelGI LightProbe Data"); RD::TextureView tv; tv.format_override = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32; lightprobe_texture = RD::get_singleton()->texture_create_shared(tv, lightprobe_data); @@ -162,11 +506,13 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V tf_ambient.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; //lightprobe texture is an octahedral texture ambient_texture = RD::get_singleton()->texture_create(tf_ambient, RD::TextureView()); + RD::get_singleton()->set_resource_name(ambient_texture, "VoxelGI Ambient Texture"); } cascades_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES); occlusion_data = RD::get_singleton()->texture_create(tf_occlusion, RD::TextureView()); + RD::get_singleton()->set_resource_name(occlusion_data, "VoxelGI Occlusion Data"); { RD::TextureView tv; tv.format_override = RD::DATA_FORMAT_R4G4B4A4_UNORM_PACK16; @@ -179,11 +525,15 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V /* 3D Textures */ cascade.sdf_tex = RD::get_singleton()->texture_create(tf_sdf, RD::TextureView()); + RD::get_singleton()->set_resource_name(cascade.sdf_tex, "VoxelGI Cascade SDF Texture"); cascade.light_data = RD::get_singleton()->texture_create(tf_light, RD::TextureView()); + RD::get_singleton()->set_resource_name(cascade.light_data, "VoxelGI Cascade Light Data"); cascade.light_aniso_0_tex = RD::get_singleton()->texture_create(tf_aniso0, RD::TextureView()); + RD::get_singleton()->set_resource_name(cascade.light_aniso_0_tex, "VoxelGI Cascade Light Aniso 0 Texture"); cascade.light_aniso_1_tex = RD::get_singleton()->texture_create(tf_aniso1, RD::TextureView()); + RD::get_singleton()->set_resource_name(cascade.light_aniso_1_tex, "VoxelGI Cascade Light Aniso 1 Texture"); { RD::TextureView tv; @@ -210,9 +560,11 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V /* Probe History */ cascade.lightprobe_history_tex = RD::get_singleton()->texture_create(tf_probe_history, RD::TextureView()); + RD::get_singleton()->set_resource_name(cascade.lightprobe_history_tex, "VoxelGI Cascade LightProbe History Texture"); RD::get_singleton()->texture_clear(cascade.lightprobe_history_tex, Color(0, 0, 0, 0), 0, 1, 0, tf_probe_history.array_layers); //needs to be cleared for average to work cascade.lightprobe_average_tex = RD::get_singleton()->texture_create(tf_probe_average, RD::TextureView()); + RD::get_singleton()->set_resource_name(cascade.lightprobe_average_tex, "VoxelGI Cascade LightProbe Average Texture"); RD::get_singleton()->texture_clear(cascade.lightprobe_average_tex, Color(0, 0, 0, 0), 0, 1, 0, 1); //needs to be cleared for average to work /* Buffers */ @@ -458,7 +810,8 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V uniforms.push_back(u); } - cascade.sdf_direct_light_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.direct_light.version_get_shader(gi->sdfgi_shader.direct_light_shader, 0), 0); + cascade.sdf_direct_light_static_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.direct_light.version_get_shader(gi->sdfgi_shader.direct_light_shader, SDFGIShader::DIRECT_LIGHT_MODE_STATIC), 0); + cascade.sdf_direct_light_dynamic_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.direct_light.version_get_shader(gi->sdfgi_shader.direct_light_shader, SDFGIShader::DIRECT_LIGHT_MODE_DYNAMIC), 0); } //preprocess initialize uniform set @@ -755,7 +1108,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V reads_sky = p_env->sdfgi_read_sky_light; } -void RendererSceneGIRD::SDFGI::erase() { +void GI::SDFGI::erase() { for (uint32_t i = 0; i < cascades.size(); i++) { const SDFGI::Cascade &c = cascades[i]; RD::get_singleton()->free(c.light_data); @@ -791,9 +1144,26 @@ void RendererSceneGIRD::SDFGI::erase() { RD::get_singleton()->free(ambient_texture); RD::get_singleton()->free(cascades_ubo); + + for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) { + if (RD::get_singleton()->uniform_set_is_valid(debug_uniform_set[v])) { + RD::get_singleton()->free(debug_uniform_set[v]); + } + debug_uniform_set[v] = RID(); + } + + if (RD::get_singleton()->uniform_set_is_valid(debug_probes_uniform_set)) { + RD::get_singleton()->free(debug_probes_uniform_set); + } + debug_probes_uniform_set = RID(); + + if (debug_probes_scene_data_ubo.is_valid()) { + RD::get_singleton()->free(debug_probes_scene_data_ubo); + debug_probes_scene_data_ubo = RID(); + } } -void RendererSceneGIRD::SDFGI::update(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position) { +void GI::SDFGI::update(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position) { bounce_feedback = p_env->sdfgi_bounce_feedback; energy = p_env->sdfgi_energy; normal_bias = p_env->sdfgi_normal_bias; @@ -851,7 +1221,7 @@ void RendererSceneGIRD::SDFGI::update(RendererSceneEnvironmentRD *p_env, const V } } -void RendererSceneGIRD::SDFGI::update_light() { +void GI::SDFGI::update_light() { RD::get_singleton()->draw_command_begin_label("SDFGI Update dynamic Light"); /* Update dynamic light */ @@ -890,7 +1260,7 @@ void RendererSceneGIRD::SDFGI::update_light() { } cascades[i].all_dynamic_lights_dirty = false; - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascade.sdf_direct_light_uniform_set, 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascade.sdf_direct_light_dynamic_uniform_set, 0); RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::DirectLightPushConstant)); RD::get_singleton()->compute_list_dispatch_indirect(compute_list, cascade.solid_cell_dispatch_buffer, 0); } @@ -898,7 +1268,7 @@ void RendererSceneGIRD::SDFGI::update_light() { RD::get_singleton()->draw_command_end_label(); } -void RendererSceneGIRD::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env, RendererSceneSkyRD::Sky *p_sky) { +void GI::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env, RendererSceneSkyRD::Sky *p_sky) { RD::get_singleton()->draw_command_begin_label("SDFGI Update Probes"); SDFGIShader::IntegratePushConstant push_constant; @@ -925,7 +1295,7 @@ void RendererSceneGIRD::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env, if (p_env->background == RS::ENV_BG_CLEAR_COLOR) { push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_COLOR; - Color c = storage->get_default_clear_color().srgb_to_linear(); + Color c = RSG::texture_storage->get_default_clear_color().srgb_to_linear(); push_constant.sky_color[0] = c.r; push_constant.sky_color[1] = c.g; push_constant.sky_color[2] = c.b; @@ -990,7 +1360,7 @@ void RendererSceneGIRD::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env, RD::get_singleton()->draw_command_end_label(); } -void RendererSceneGIRD::SDFGI::store_probes() { +void GI::SDFGI::store_probes() { RD::get_singleton()->barrier(RD::BARRIER_MASK_COMPUTE, RD::BARRIER_MASK_COMPUTE); RD::get_singleton()->draw_command_begin_label("SDFGI Store Probes"); @@ -1035,7 +1405,7 @@ void RendererSceneGIRD::SDFGI::store_probes() { RD::get_singleton()->draw_command_end_label(); } -int RendererSceneGIRD::SDFGI::get_pending_region_data(int p_region, Vector3i &r_local_offset, Vector3i &r_local_size, AABB &r_bounds) const { +int GI::SDFGI::get_pending_region_data(int p_region, Vector3i &r_local_offset, Vector3i &r_local_size, AABB &r_bounds) const { int dirty_count = 0; for (uint32_t i = 0; i < cascades.size(); i++) { const SDFGI::Cascade &c = cascades[i]; @@ -1091,7 +1461,7 @@ int RendererSceneGIRD::SDFGI::get_pending_region_data(int p_region, Vector3i &r_ return -1; } -void RendererSceneGIRD::SDFGI::update_cascades() { +void GI::SDFGI::update_cascades() { //update cascades SDFGI::Cascade::UBO cascade_data[SDFGI::MAX_CASCADES]; int32_t probe_divisor = cascade_size / SDFGI::PROBE_DIVISOR; @@ -1112,160 +1482,177 @@ void RendererSceneGIRD::SDFGI::update_cascades() { RD::get_singleton()->buffer_update(cascades_ubo, 0, sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES, cascade_data, RD::BARRIER_MASK_COMPUTE); } -void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture) { +void GI::SDFGI::debug_draw(uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture, const Vector<RID> &p_texture_views) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); - if (!debug_uniform_set.is_valid() || !RD::get_singleton()->uniform_set_is_valid(debug_uniform_set)) { - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.binding = 1; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) { - if (i < cascades.size()) { - u.append_id(cascades[i].sdf_tex); - } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + for (uint32_t v = 0; v < p_view_count; v++) { + if (!debug_uniform_set[v].is_valid() || !RD::get_singleton()->uniform_set_is_valid(debug_uniform_set[v])) { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.binding = 1; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) { + if (i < cascades.size()) { + u.append_id(cascades[i].sdf_tex); + } else { + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + } } + uniforms.push_back(u); } - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 2; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) { - if (i < cascades.size()) { - u.append_id(cascades[i].light_tex); - } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + { + RD::Uniform u; + u.binding = 2; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) { + if (i < cascades.size()) { + u.append_id(cascades[i].light_tex); + } else { + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + } } + uniforms.push_back(u); } - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 3; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) { - if (i < cascades.size()) { - u.append_id(cascades[i].light_aniso_0_tex); - } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + { + RD::Uniform u; + u.binding = 3; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) { + if (i < cascades.size()) { + u.append_id(cascades[i].light_aniso_0_tex); + } else { + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + } } + uniforms.push_back(u); } - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 4; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) { - if (i < cascades.size()) { - u.append_id(cascades[i].light_aniso_1_tex); - } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + { + RD::Uniform u; + u.binding = 4; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) { + if (i < cascades.size()) { + u.append_id(cascades[i].light_aniso_1_tex); + } else { + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + } } + uniforms.push_back(u); } - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 5; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.append_id(occlusion_texture); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 8; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; - u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 9; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.append_id(cascades_ubo); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 10; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.append_id(p_texture); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 11; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.append_id(lightprobe_texture); - uniforms.push_back(u); + { + RD::Uniform u; + u.binding = 5; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.append_id(occlusion_texture); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 8; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; + u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 9; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.append_id(cascades_ubo); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 10; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.append_id(p_texture_views[v]); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 11; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.append_id(lightprobe_texture); + uniforms.push_back(u); + } + debug_uniform_set[v] = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.debug_shader_version, 0); } - debug_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.debug_shader_version, 0); - } - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.debug_pipeline); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, debug_uniform_set, 0); - SDFGIShader::DebugPushConstant push_constant; - push_constant.grid_size[0] = cascade_size; - push_constant.grid_size[1] = cascade_size; - push_constant.grid_size[2] = cascade_size; - push_constant.max_cascades = cascades.size(); - push_constant.screen_size[0] = p_width; - push_constant.screen_size[1] = p_height; - push_constant.probe_axis_size = probe_axis_count; - push_constant.use_occlusion = uses_occlusion; - push_constant.y_mult = y_mult; - - Vector2 vp_half = p_projection.get_viewport_half_extents(); - push_constant.cam_extent[0] = vp_half.x; - push_constant.cam_extent[1] = vp_half.y; - push_constant.cam_extent[2] = -p_projection.get_z_near(); - - push_constant.cam_transform[0] = p_transform.basis.rows[0][0]; - push_constant.cam_transform[1] = p_transform.basis.rows[1][0]; - push_constant.cam_transform[2] = p_transform.basis.rows[2][0]; - push_constant.cam_transform[3] = 0; - push_constant.cam_transform[4] = p_transform.basis.rows[0][1]; - push_constant.cam_transform[5] = p_transform.basis.rows[1][1]; - push_constant.cam_transform[6] = p_transform.basis.rows[2][1]; - push_constant.cam_transform[7] = 0; - push_constant.cam_transform[8] = p_transform.basis.rows[0][2]; - push_constant.cam_transform[9] = p_transform.basis.rows[1][2]; - push_constant.cam_transform[10] = p_transform.basis.rows[2][2]; - push_constant.cam_transform[11] = 0; - push_constant.cam_transform[12] = p_transform.origin.x; - push_constant.cam_transform[13] = p_transform.origin.y; - push_constant.cam_transform[14] = p_transform.origin.z; - push_constant.cam_transform[15] = 1; - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::DebugPushConstant)); - - RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_width, p_height, 1); - RD::get_singleton()->compute_list_end(); + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.debug_pipeline); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, debug_uniform_set[v], 0); + + SDFGIShader::DebugPushConstant push_constant; + push_constant.grid_size[0] = cascade_size; + push_constant.grid_size[1] = cascade_size; + push_constant.grid_size[2] = cascade_size; + push_constant.max_cascades = cascades.size(); + push_constant.screen_size[0] = p_width; + push_constant.screen_size[1] = p_height; + push_constant.probe_axis_size = probe_axis_count; + push_constant.use_occlusion = uses_occlusion; + push_constant.y_mult = y_mult; + + push_constant.z_near = -p_projections[v].get_z_near(); + + push_constant.cam_transform[0] = p_transform.basis.rows[0][0]; + push_constant.cam_transform[1] = p_transform.basis.rows[1][0]; + push_constant.cam_transform[2] = p_transform.basis.rows[2][0]; + push_constant.cam_transform[3] = 0; + push_constant.cam_transform[4] = p_transform.basis.rows[0][1]; + push_constant.cam_transform[5] = p_transform.basis.rows[1][1]; + push_constant.cam_transform[6] = p_transform.basis.rows[2][1]; + push_constant.cam_transform[7] = 0; + push_constant.cam_transform[8] = p_transform.basis.rows[0][2]; + push_constant.cam_transform[9] = p_transform.basis.rows[1][2]; + push_constant.cam_transform[10] = p_transform.basis.rows[2][2]; + push_constant.cam_transform[11] = 0; + push_constant.cam_transform[12] = p_transform.origin.x; + push_constant.cam_transform[13] = p_transform.origin.y; + push_constant.cam_transform[14] = p_transform.origin.z; + push_constant.cam_transform[15] = 1; + + // need to properly unproject for asymmetric projection matrices in stereo.. + CameraMatrix inv_projection = p_projections[v].inverse(); + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + push_constant.inv_projection[i * 4 + j] = inv_projection.matrix[i][j]; + } + } + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::DebugPushConstant)); + + RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_width, p_height, 1); + RD::get_singleton()->compute_list_end(); + } Size2 rtsize = texture_storage->render_target_get_size(p_render_target); - copy_effects->copy_to_fb_rect(p_texture, texture_storage->render_target_get_rd_framebuffer(p_render_target), Rect2(Vector2(), rtsize), true); + copy_effects->copy_to_fb_rect(p_texture, texture_storage->render_target_get_rd_framebuffer(p_render_target), Rect2(Vector2(), rtsize), true, false, false, false, RID(), p_view_count > 1); } -void RendererSceneGIRD::SDFGI::debug_probes(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform) { +void GI::SDFGI::debug_probes(RID p_framebuffer, const uint32_t p_view_count, const CameraMatrix *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) { RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - SDFGIShader::DebugProbesPushConstant push_constant; + // setup scene data + { + SDFGIShader::DebugProbesSceneData scene_data; - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - push_constant.projection[i * 4 + j] = p_camera_with_transform.matrix[i][j]; + if (debug_probes_scene_data_ubo.is_null()) { + debug_probes_scene_data_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SDFGIShader::DebugProbesSceneData)); + } + + for (uint32_t v = 0; v < p_view_count; v++) { + RendererRD::MaterialStorage::store_camera(p_camera_with_transforms[v], scene_data.projection[v]); } + + RD::get_singleton()->buffer_update(debug_probes_scene_data_ubo, 0, sizeof(SDFGIShader::DebugProbesSceneData), &scene_data, RD::BARRIER_MASK_RASTER); } + // setup push constant + SDFGIShader::DebugProbesPushConstant push_constant; + //gen spheres from strips uint32_t band_points = 16; push_constant.band_power = 4; @@ -1314,14 +1701,26 @@ void RendererSceneGIRD::SDFGI::debug_probes(RD::DrawListID p_draw_list, RID p_fr u.append_id(occlusion_texture); uniforms.push_back(u); } + { + RD::Uniform u; + u.binding = 5; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.append_id(debug_probes_scene_data_ubo); + uniforms.push_back(u); + } debug_probes_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.debug_probes.version_get_shader(gi->sdfgi_shader.debug_probes_shader, 0), 0); } - RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, gi->sdfgi_shader.debug_probes_pipeline[SDFGIShader::PROBE_DEBUG_PROBES].get_render_pipeline(RD::INVALID_FORMAT_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, debug_probes_uniform_set, 0); - RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(SDFGIShader::DebugProbesPushConstant)); - RD::get_singleton()->draw_list_draw(p_draw_list, false, total_probes, total_points); + SDFGIShader::ProbeDebugMode mode = p_view_count > 1 ? SDFGIShader::PROBE_DEBUG_PROBES_MULTIVIEW : SDFGIShader::PROBE_DEBUG_PROBES; + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CONTINUE, p_will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, p_will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); + RD::get_singleton()->draw_command_begin_label("Debug SDFGI"); + + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, gi->sdfgi_shader.debug_probes_pipeline[mode].get_render_pipeline(RD::INVALID_FORMAT_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, debug_probes_uniform_set, 0); + RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(SDFGIShader::DebugProbesPushConstant)); + RD::get_singleton()->draw_list_draw(draw_list, false, total_probes, total_points); if (gi->sdfgi_debug_probe_dir != Vector3()) { uint32_t cascade = 0; @@ -1373,14 +1772,17 @@ void RendererSceneGIRD::SDFGI::debug_probes(RD::DrawListID p_draw_list, RID p_fr uint32_t cell_count = probe_cells * 2 * probe_cells * 2 * probe_cells * 2; - RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, gi->sdfgi_shader.debug_probes_pipeline[SDFGIShader::PROBE_DEBUG_VISIBILITY].get_render_pipeline(RD::INVALID_FORMAT_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, debug_probes_uniform_set, 0); - RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(SDFGIShader::DebugProbesPushConstant)); - RD::get_singleton()->draw_list_draw(p_draw_list, false, cell_count, total_points); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, gi->sdfgi_shader.debug_probes_pipeline[p_view_count > 1 ? SDFGIShader::PROBE_DEBUG_VISIBILITY_MULTIVIEW : SDFGIShader::PROBE_DEBUG_VISIBILITY].get_render_pipeline(RD::INVALID_FORMAT_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, debug_probes_uniform_set, 0); + RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(SDFGIShader::DebugProbesPushConstant)); + RD::get_singleton()->draw_list_draw(draw_list, false, cell_count, total_points); } + + RD::get_singleton()->draw_command_end_label(); + RD::get_singleton()->draw_list_end(); } -void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data, RendererSceneRenderRD *p_scene_render) { +void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data, RendererSceneRenderRD *p_scene_render) { /* Update general SDFGI Buffer */ SDFGIData sdfgi_data; @@ -1545,7 +1947,7 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re } } -void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArray<RendererSceneRender::GeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render) { +void GI::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArray<RendererSceneRender::GeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render) { //print_line("rendering region " + itos(p_region)); RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND(!rb); // we wouldn't be here if this failed but... @@ -1904,7 +2306,7 @@ void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region, } } -void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render) { +void GI::SDFGI::render_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render) { RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND(!rb); // we wouldn't be here if this failed but... @@ -2012,7 +2414,7 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32 dl_push_constant.cascade = p_cascade_indices[i]; if (dl_push_constant.light_count > 0) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cc.sdf_direct_light_uniform_set, 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cc.sdf_direct_light_static_uniform_set, 0); RD::get_singleton()->compute_list_set_push_constant(compute_list, &dl_push_constant, sizeof(SDFGIShader::DirectLightPushConstant)); RD::get_singleton()->compute_list_dispatch_indirect(compute_list, cc.solid_cell_dispatch_buffer, 0); } @@ -2026,10 +2428,10 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32 //////////////////////////////////////////////////////////////////////////////// // VoxelGIInstance -void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) { +void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) { RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - uint32_t data_version = storage->voxel_gi_get_data_version(probe); + uint32_t data_version = gi->voxel_gi_get_data_version(probe); // (RE)CREATE IF NEEDED @@ -2048,11 +2450,11 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c dynamic_maps.clear(); - Vector3i octree_size = storage->voxel_gi_get_octree_size(probe); + Vector3i octree_size = gi->voxel_gi_get_octree_size(probe); if (octree_size != Vector3i()) { //can create a 3D texture - Vector<int> levels = storage->voxel_gi_get_level_counts(probe); + Vector<int> levels = gi->voxel_gi_get_level_counts(probe); RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; @@ -2065,6 +2467,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(texture, "VoxelGI Instance Texture"); RD::get_singleton()->texture_clear(texture, Color(0, 0, 0, 0), 0, levels.size(), 0, 1); @@ -2092,14 +2495,14 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 1; - u.append_id(storage->voxel_gi_get_octree_buffer(probe)); + u.append_id(gi->voxel_gi_get_octree_buffer(probe)); uniforms.push_back(u); } { RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 2; - u.append_id(storage->voxel_gi_get_data_buffer(probe)); + u.append_id(gi->voxel_gi_get_data_buffer(probe)); uniforms.push_back(u); } @@ -2114,7 +2517,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 9; - u.append_id(storage->voxel_gi_get_sdf_texture(probe)); + u.append_id(gi->voxel_gi_get_sdf_texture(probe)); uniforms.push_back(u); } { @@ -2194,6 +2597,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c dtf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; } dmap.texture = RD::get_singleton()->texture_create(dtf, RD::TextureView()); + RD::get_singleton()->set_resource_name(dmap.texture, "VoxelGI Instance DMap Texture"); if (dynamic_maps.size() == 0) { // Render depth for first one. @@ -2201,6 +2605,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c dtf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D16_UNORM, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D16_UNORM : RD::DATA_FORMAT_X8_D24_UNORM_PACK32; dtf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; dmap.fb_depth = RD::get_singleton()->texture_create(dtf, RD::TextureView()); + RD::get_singleton()->set_resource_name(dmap.fb_depth, "VoxelGI Instance DMap FB Depth"); } //just use depth as-is @@ -2208,13 +2613,17 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; dmap.depth = RD::get_singleton()->texture_create(dtf, RD::TextureView()); + RD::get_singleton()->set_resource_name(dmap.depth, "VoxelGI Instance DMap Depth"); if (dynamic_maps.size() == 0) { dtf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; dmap.albedo = RD::get_singleton()->texture_create(dtf, RD::TextureView()); + RD::get_singleton()->set_resource_name(dmap.albedo, "VoxelGI Instance DMap Albedo"); dmap.normal = RD::get_singleton()->texture_create(dtf, RD::TextureView()); + RD::get_singleton()->set_resource_name(dmap.normal, "VoxelGI Instance DMap Normal"); dmap.orm = RD::get_singleton()->texture_create(dtf, RD::TextureView()); + RD::get_singleton()->set_resource_name(dmap.orm, "VoxelGI Instance DMap ORM"); Vector<RID> fb; fb.push_back(dmap.albedo); @@ -2268,7 +2677,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 9; - u.append_id(storage->voxel_gi_get_sdf_texture(probe)); + u.append_id(gi->voxel_gi_get_sdf_texture(probe)); uniforms.push_back(u); } { @@ -2337,7 +2746,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 9; - u.append_id(storage->voxel_gi_get_sdf_texture(probe)); + u.append_id(gi->voxel_gi_get_sdf_texture(probe)); uniforms.push_back(u); } { @@ -2388,7 +2797,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c light_count = MIN(gi->voxel_gi_max_lights, (uint32_t)p_light_instances.size()); { - Transform3D to_cell = storage->voxel_gi_get_to_cell_xform(probe); + Transform3D to_cell = gi->voxel_gi_get_to_cell_xform(probe); Transform3D to_probe_xform = (transform * to_cell.affine_inverse()).affine_inverse(); //update lights @@ -2439,7 +2848,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c if (mipmaps.size()) { //can update mipmaps - Vector3i probe_size = storage->voxel_gi_get_octree_size(probe); + Vector3i probe_size = gi->voxel_gi_get_octree_size(probe); VoxelGIPushConstant push_constant; @@ -2448,8 +2857,8 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c push_constant.limits[2] = probe_size.z; push_constant.stack_size = mipmaps.size(); push_constant.emission_scale = 1.0; - push_constant.propagation = storage->voxel_gi_get_propagation(probe); - push_constant.dynamic_range = storage->voxel_gi_get_dynamic_range(probe); + push_constant.propagation = gi->voxel_gi_get_propagation(probe); + push_constant.dynamic_range = gi->voxel_gi_get_dynamic_range(probe); push_constant.light_count = light_count; push_constant.aniso_strength = 0; @@ -2461,7 +2870,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c int passes; if (p_update_light_instances) { - passes = storage->voxel_gi_is_using_two_bounces(probe) ? 2 : 1; + passes = gi->voxel_gi_is_using_two_bounces(probe) ? 2 : 1; } else { passes = 1; //only re-blitting is necessary } @@ -2528,13 +2937,13 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c has_dynamic_object_data = false; //clear until dynamic object data is used again if (p_dynamic_objects.size() && dynamic_maps.size()) { - Vector3i octree_size = storage->voxel_gi_get_octree_size(probe); + Vector3i octree_size = gi->voxel_gi_get_octree_size(probe); int multiplier = dynamic_maps[0].size / MAX(MAX(octree_size.x, octree_size.y), octree_size.z); Transform3D oversample_scale; oversample_scale.basis.scale(Vector3(multiplier, multiplier, multiplier)); - Transform3D to_cell = oversample_scale * storage->voxel_gi_get_to_cell_xform(probe); + Transform3D to_cell = oversample_scale * gi->voxel_gi_get_to_cell_xform(probe); Transform3D to_world_xform = transform * to_cell.affine_inverse(); Transform3D to_probe_xform = to_world_xform.affine_inverse(); @@ -2634,7 +3043,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c push_constant.z_base = xform.origin[z_axis]; push_constant.z_sign = (z_flip ? -1.0 : 1.0); push_constant.pos_multiplier = float(1.0) / multiplier; - push_constant.dynamic_range = storage->voxel_gi_get_dynamic_range(probe); + push_constant.dynamic_range = gi->voxel_gi_get_dynamic_range(probe); push_constant.flip_x = x_flip; push_constant.flip_y = y_flip; push_constant.rect_pos[0] = rect.position[0]; @@ -2646,7 +3055,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c push_constant.prev_rect_size[0] = 0; push_constant.prev_rect_size[1] = 0; push_constant.on_mipmap = false; - push_constant.propagation = storage->voxel_gi_get_propagation(probe); + push_constant.propagation = gi->voxel_gi_get_propagation(probe); push_constant.pad[0] = 0; push_constant.pad[1] = 0; push_constant.pad[2] = 0; @@ -2728,24 +3137,24 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c has_dynamic_object_data = true; //clear until dynamic object data is used again } - last_probe_version = storage->voxel_gi_get_version(probe); + last_probe_version = gi->voxel_gi_get_version(probe); } -void RendererSceneGIRD::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) { +void GI::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) { RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); if (mipmaps.size() == 0) { return; } - CameraMatrix cam_transform = (p_camera_with_transform * CameraMatrix(transform)) * CameraMatrix(storage->voxel_gi_get_to_cell_xform(probe).affine_inverse()); + CameraMatrix cam_transform = (p_camera_with_transform * CameraMatrix(transform)) * CameraMatrix(gi->voxel_gi_get_to_cell_xform(probe).affine_inverse()); int level = 0; - Vector3i octree_size = storage->voxel_gi_get_octree_size(probe); + Vector3i octree_size = gi->voxel_gi_get_octree_size(probe); VoxelGIDebugPushConstant push_constant; push_constant.alpha = p_alpha; - push_constant.dynamic_range = storage->voxel_gi_get_dynamic_range(probe); + push_constant.dynamic_range = gi->voxel_gi_get_dynamic_range(probe); push_constant.cell_offset = mipmaps[level].cell_offset; push_constant.level = level; @@ -2768,7 +3177,7 @@ void RendererSceneGIRD::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; u.binding = 1; - u.append_id(storage->voxel_gi_get_data_buffer(probe)); + u.append_id(gi->voxel_gi_get_data_buffer(probe)); uniforms.push_back(u); } { @@ -2810,23 +3219,24 @@ void RendererSceneGIRD::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p } //////////////////////////////////////////////////////////////////////////////// -// GIRD +// GI + +GI::GI() { + singleton = this; -RendererSceneGIRD::RendererSceneGIRD() { sdfgi_ray_count = RS::EnvironmentSDFGIRayCount(CLAMP(int32_t(GLOBAL_GET("rendering/global_illumination/sdfgi/probe_ray_count")), 0, int32_t(RS::ENV_SDFGI_RAY_COUNT_MAX - 1))); sdfgi_frames_to_converge = RS::EnvironmentSDFGIFramesToConverge(CLAMP(int32_t(GLOBAL_GET("rendering/global_illumination/sdfgi/frames_to_converge")), 0, int32_t(RS::ENV_SDFGI_CONVERGE_MAX - 1))); sdfgi_frames_to_update_light = RS::EnvironmentSDFGIFramesToUpdateLight(CLAMP(int32_t(GLOBAL_GET("rendering/global_illumination/sdfgi/frames_to_update_lights")), 0, int32_t(RS::ENV_SDFGI_UPDATE_LIGHT_MAX - 1))); } -RendererSceneGIRD::~RendererSceneGIRD() { +GI::~GI() { + singleton = nullptr; } -void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p_sky) { +void GI::init(RendererSceneSkyRD *p_sky) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - storage = p_storage; - /* GI */ { @@ -2942,7 +3352,11 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 0; - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE)); + if (p_sky->sky_use_cubemap_array) { + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_WHITE)); + } else { + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE)); + } uniforms.push_back(u); } { @@ -2962,17 +3376,41 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p //calculate tables String defines = "\n#define SDFGI_OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; Vector<String> gi_modes; - gi_modes.push_back("\n#define USE_VOXEL_GI_INSTANCES\n"); - gi_modes.push_back("\n#define USE_SDFGI\n"); - gi_modes.push_back("\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n"); - gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_VOXEL_GI_INSTANCES\n"); - gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n"); - gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n"); + + gi_modes.push_back("\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_VOXEL_GI + gi_modes.push_back("\n#define USE_SDFGI\n"); // MODE_SDFGI + gi_modes.push_back("\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_COMBINED shader.initialize(gi_modes, defines); shader_version = shader.version_create(); - for (int i = 0; i < MODE_MAX; i++) { - pipelines[i] = RD::get_singleton()->compute_pipeline_create(shader.version_get_shader(shader_version, i)); + + Vector<RD::PipelineSpecializationConstant> specialization_constants; + + { + RD::PipelineSpecializationConstant sc; + sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL; + sc.constant_id = 0; // SHADER_SPECIALIZATION_HALF_RES + sc.bool_value = false; + specialization_constants.push_back(sc); + + sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL; + sc.constant_id = 1; // SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX + sc.bool_value = false; + specialization_constants.push_back(sc); + + sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL; + sc.constant_id = 2; // SHADER_SPECIALIZATION_USE_VRS + sc.bool_value = false; + specialization_constants.push_back(sc); + } + + for (int v = 0; v < SHADER_SPECIALIZATION_VARIATIONS; v++) { + specialization_constants.ptrw()[0].bool_value = (v & SHADER_SPECIALIZATION_HALF_RES) ? true : false; + specialization_constants.ptrw()[1].bool_value = (v & SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX) ? true : false; + specialization_constants.ptrw()[2].bool_value = (v & SHADER_SPECIALIZATION_USE_VRS) ? true : false; + for (int i = 0; i < MODE_MAX; i++) { + pipelines[v][i] = RD::get_singleton()->compute_pipeline_create(shader.version_get_shader(shader_version, i), specialization_constants); + } } sdfgi_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SDFGIData)); @@ -2991,9 +3429,14 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p Vector<String> versions; versions.push_back("\n#define MODE_PROBES\n"); + versions.push_back("\n#define MODE_PROBES\n#define USE_MULTIVIEW\n"); versions.push_back("\n#define MODE_VISIBILITY\n"); + versions.push_back("\n#define MODE_VISIBILITY\n#define USE_MULTIVIEW\n"); sdfgi_shader.debug_probes.initialize(versions, defines); + + // TODO disable multiview versions if turned off + sdfgi_shader.debug_probes_shader = sdfgi_shader.debug_probes.version_create(); { @@ -3004,6 +3447,8 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p ds.enable_depth_write = true; ds.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL; for (int i = 0; i < SDFGIShader::PROBE_DEBUG_MAX; i++) { + // TODO check if version is enabled + RID debug_probes_shader_version = sdfgi_shader.debug_probes.version_get_shader(sdfgi_shader.debug_probes_shader, i); sdfgi_shader.debug_probes_pipeline[i].setup(debug_probes_shader_version, RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0); } @@ -3013,7 +3458,7 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p half_resolution = GLOBAL_GET("rendering/global_illumination/gi/use_half_resolution"); } -void RendererSceneGIRD::free() { +void GI::free() { RD::get_singleton()->free(default_voxel_gi_buffer); RD::get_singleton()->free(voxel_gi_lights_uniform); RD::get_singleton()->free(sdfgi_ubo); @@ -3032,7 +3477,7 @@ void RendererSceneGIRD::free() { } } -RendererSceneGIRD::SDFGI *RendererSceneGIRD::create_sdfgi(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size) { +GI::SDFGI *GI::create_sdfgi(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size) { SDFGI *sdfgi = memnew(SDFGI); sdfgi->create(p_env, p_world_position, p_requested_history_size, this); @@ -3040,7 +3485,7 @@ RendererSceneGIRD::SDFGI *RendererSceneGIRD::create_sdfgi(RendererSceneEnvironme return sdfgi; } -void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render) { +void GI::setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); r_voxel_gi_instances_used = 0; @@ -3069,7 +3514,7 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra RID base_probe = gipi->probe; - Transform3D to_cell = storage->voxel_gi_get_to_cell_xform(gipi->probe) * gipi->transform.affine_inverse() * to_camera; + Transform3D to_cell = voxel_gi_get_to_cell_xform(gipi->probe) * gipi->transform.affine_inverse() * to_camera; gipd.xform[0] = to_cell.basis.rows[0][0]; gipd.xform[1] = to_cell.basis.rows[1][0]; @@ -3088,16 +3533,16 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra gipd.xform[14] = to_cell.origin.z; gipd.xform[15] = 1; - Vector3 bounds = storage->voxel_gi_get_octree_size(base_probe); + Vector3 bounds = voxel_gi_get_octree_size(base_probe); gipd.bounds[0] = bounds.x; gipd.bounds[1] = bounds.y; gipd.bounds[2] = bounds.z; - gipd.dynamic_range = storage->voxel_gi_get_dynamic_range(base_probe) * storage->voxel_gi_get_energy(base_probe); - gipd.bias = storage->voxel_gi_get_bias(base_probe); - gipd.normal_bias = storage->voxel_gi_get_normal_bias(base_probe); - gipd.blend_ambient = !storage->voxel_gi_is_interior(base_probe); + gipd.dynamic_range = voxel_gi_get_dynamic_range(base_probe) * voxel_gi_get_energy(base_probe); + gipd.bias = voxel_gi_get_bias(base_probe); + gipd.normal_bias = voxel_gi_get_normal_bias(base_probe); + gipd.blend_ambient = !voxel_gi_is_interior(base_probe); gipd.mipmaps = gipi->mipmaps.size(); } @@ -3108,17 +3553,19 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE); } - if (texture != rb->gi.voxel_gi_textures[i]) { + if (texture != rb->rbgi.voxel_gi_textures[i]) { voxel_gi_instances_changed = true; - rb->gi.voxel_gi_textures[i] = texture; + rb->rbgi.voxel_gi_textures[i] = texture; } } if (voxel_gi_instances_changed) { - if (RD::get_singleton()->uniform_set_is_valid(rb->gi.uniform_set)) { - RD::get_singleton()->free(rb->gi.uniform_set); + for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) { + if (RD::get_singleton()->uniform_set_is_valid(rb->rbgi.uniform_set[v])) { + RD::get_singleton()->free(rb->rbgi.uniform_set[v]); + } + rb->rbgi.uniform_set[v] = RID(); } - rb->gi.uniform_set = RID(); if (rb->volumetric_fog) { if (RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->fog_uniform_set)) { RD::get_singleton()->free(rb->volumetric_fog->fog_uniform_set); @@ -3140,21 +3587,67 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra } } -void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) { +void GI::RenderBuffersGI::free() { + for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) { + if (RD::get_singleton()->uniform_set_is_valid(uniform_set[v])) { + RD::get_singleton()->free(uniform_set[v]); + } + uniform_set[v] = RID(); + } + + if (scene_data_ubo.is_valid()) { + RD::get_singleton()->free(scene_data_ubo); + scene_data_ubo = RID(); + } + + if (ambient_buffer.is_valid()) { + RD::get_singleton()->free(ambient_buffer); + RD::get_singleton()->free(reflection_buffer); + ambient_buffer = RID(); + reflection_buffer = RID(); + + // these are automatically freed when we free the textures, so just reset.. + for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) { + ambient_slice[v] = RID(); + reflection_slice[v] = RID(); + } + + view_count = 0; + } + + if (voxel_gi_buffer.is_valid()) { + RD::get_singleton()->free(voxel_gi_buffer); + voxel_gi_buffer = RID(); + } +} + +void GI::process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices, RID p_environment, uint32_t p_view_count, const CameraMatrix *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); + ERR_FAIL_COND_MSG(p_view_count > 2, "Maximum of 2 views supported for Processing GI."); + RD::get_singleton()->draw_command_begin_label("GI Render"); RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND(rb == nullptr); - if (rb->ambient_buffer.is_null() || rb->gi.using_half_size_gi != half_resolution) { - if (rb->ambient_buffer.is_valid()) { - RD::get_singleton()->free(rb->ambient_buffer); - RD::get_singleton()->free(rb->reflection_buffer); + if (rb->rbgi.ambient_buffer.is_null() || rb->rbgi.using_half_size_gi != half_resolution || rb->rbgi.view_count != p_view_count) { + // Free our old buffer if applicable + if (rb->rbgi.ambient_buffer.is_valid()) { + RD::get_singleton()->free(rb->rbgi.ambient_buffer); + RD::get_singleton()->free(rb->rbgi.reflection_buffer); + + for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) { + rb->rbgi.ambient_slice[v] = RID(); + rb->rbgi.reflection_slice[v] = RID(); + } } + // Remember the view count we're using + rb->rbgi.view_count = p_view_count; + + // Create textures for our ambient and reflection data RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; tf.width = rb->internal_width; @@ -3163,252 +3656,318 @@ void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_ tf.width >>= 1; tf.height >>= 1; } + if (p_view_count > 1) { + tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + tf.array_layers = p_view_count; + } else { + tf.texture_type = RD::TEXTURE_TYPE_2D; + tf.array_layers = 1; + } tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - rb->reflection_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); - rb->ambient_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); - rb->gi.using_half_size_gi = half_resolution; + rb->rbgi.ambient_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(rb->rbgi.ambient_buffer, "GI Ambient Buffer"); + rb->rbgi.reflection_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); + RD::get_singleton()->set_resource_name(rb->rbgi.reflection_buffer, "GI Reflection Buffer"); + rb->rbgi.using_half_size_gi = half_resolution; + + if (p_view_count == 1) { + // Just copy, we don't need to create slices + rb->rbgi.ambient_slice[0] = rb->rbgi.ambient_buffer; + rb->rbgi.reflection_slice[0] = rb->rbgi.reflection_buffer; + } else { + for (uint32_t v = 0; v < p_view_count; v++) { + rb->rbgi.ambient_slice[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.ambient_buffer, v, 0); + rb->rbgi.reflection_slice[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->rbgi.reflection_buffer, v, 0); + } + } } + // Setup our scene data + { + SceneData scene_data; + + if (rb->rbgi.scene_data_ubo.is_null()) { + rb->rbgi.scene_data_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SceneData)); + } + + for (uint32_t v = 0; v < p_view_count; v++) { + RendererRD::MaterialStorage::store_camera(p_projections[v].inverse(), scene_data.inv_projection[v]); + scene_data.eye_offset[v][0] = p_eye_offsets[v].x; + scene_data.eye_offset[v][1] = p_eye_offsets[v].y; + scene_data.eye_offset[v][2] = p_eye_offsets[v].z; + scene_data.eye_offset[v][3] = 0.0; + } + + // Note that we will be ignoring the origin of this transform. + RendererRD::MaterialStorage::store_transform(p_cam_transform, scene_data.cam_transform); + + scene_data.screen_size[0] = rb->internal_width; + scene_data.screen_size[1] = rb->internal_height; + + RD::get_singleton()->buffer_update(rb->rbgi.scene_data_ubo, 0, sizeof(SceneData), &scene_data, RD::BARRIER_MASK_COMPUTE); + } + + // Now compute the contents of our buffers. + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(true); + + // Render each eye seperately. + // We need to look into whether we can make our compute shader use Multiview but not sure that works or makes a difference.. + + // setup our push constant + PushConstant push_constant; - push_constant.screen_size[0] = rb->internal_width; - push_constant.screen_size[1] = rb->internal_height; - push_constant.z_near = p_projection.get_z_near(); - push_constant.z_far = p_projection.get_z_far(); - push_constant.orthogonal = p_projection.is_orthogonal(); - push_constant.proj_info[0] = -2.0f / (rb->internal_width * p_projection.matrix[0][0]); - push_constant.proj_info[1] = -2.0f / (rb->internal_height * p_projection.matrix[1][1]); - push_constant.proj_info[2] = (1.0f - p_projection.matrix[0][2]) / p_projection.matrix[0][0]; - push_constant.proj_info[3] = (1.0f + p_projection.matrix[1][2]) / p_projection.matrix[1][1]; push_constant.max_voxel_gi_instances = MIN((uint64_t)MAX_VOXEL_GI_INSTANCES, p_voxel_gi_instances.size()); push_constant.high_quality_vct = voxel_gi_quality == RS::VOXEL_GI_QUALITY_HIGH; + // these should be the same for all views + push_constant.orthogonal = p_projections[0].is_orthogonal(); + push_constant.z_near = p_projections[0].get_z_near(); + push_constant.z_far = p_projections[0].get_z_far(); + + // these are only used if we have 1 view, else we use the projections in our scene data + push_constant.proj_info[0] = -2.0f / (rb->internal_width * p_projections[0].matrix[0][0]); + push_constant.proj_info[1] = -2.0f / (rb->internal_height * p_projections[0].matrix[1][1]); + push_constant.proj_info[2] = (1.0f - p_projections[0].matrix[0][2]) / p_projections[0].matrix[0][0]; + push_constant.proj_info[3] = (1.0f + p_projections[0].matrix[1][2]) / p_projections[0].matrix[1][1]; + bool use_sdfgi = rb->sdfgi != nullptr; bool use_voxel_gi_instances = push_constant.max_voxel_gi_instances > 0; - push_constant.cam_rotation[0] = p_transform.basis[0][0]; - push_constant.cam_rotation[1] = p_transform.basis[1][0]; - push_constant.cam_rotation[2] = p_transform.basis[2][0]; - push_constant.cam_rotation[3] = 0; - push_constant.cam_rotation[4] = p_transform.basis[0][1]; - push_constant.cam_rotation[5] = p_transform.basis[1][1]; - push_constant.cam_rotation[6] = p_transform.basis[2][1]; - push_constant.cam_rotation[7] = 0; - push_constant.cam_rotation[8] = p_transform.basis[0][2]; - push_constant.cam_rotation[9] = p_transform.basis[1][2]; - push_constant.cam_rotation[10] = p_transform.basis[2][2]; - push_constant.cam_rotation[11] = 0; - - if (rb->gi.uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->gi.uniform_set)) { - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.binding = 1; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { - if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { - u.append_id(rb->sdfgi->cascades[j].sdf_tex); - } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + uint32_t pipeline_specialization = 0; + if (rb->rbgi.using_half_size_gi) { + pipeline_specialization |= SHADER_SPECIALIZATION_HALF_RES; + } + if (p_view_count > 1) { + pipeline_specialization |= SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX; + } + if (p_vrs_slices[0].is_valid()) { + pipeline_specialization |= SHADER_SPECIALIZATION_USE_VRS; + } + + Mode mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_COMBINED : (use_sdfgi ? MODE_SDFGI : MODE_VOXEL_GI); + + for (uint32_t v = 0; v < p_view_count; v++) { + push_constant.view_index = v; + + // setup our uniform set + if (rb->rbgi.uniform_set[v].is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->rbgi.uniform_set[v])) { + Vector<RD::Uniform> uniforms; + { + RD::Uniform u; + u.binding = 1; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { + if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { + u.append_id(rb->sdfgi->cascades[j].sdf_tex); + } else { + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + } } + uniforms.push_back(u); } - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 2; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { - if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { - u.append_id(rb->sdfgi->cascades[j].light_tex); - } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + { + RD::Uniform u; + u.binding = 2; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { + if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { + u.append_id(rb->sdfgi->cascades[j].light_tex); + } else { + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + } } + uniforms.push_back(u); } - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 3; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { - if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { - u.append_id(rb->sdfgi->cascades[j].light_aniso_0_tex); - } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + { + RD::Uniform u; + u.binding = 3; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { + if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { + u.append_id(rb->sdfgi->cascades[j].light_aniso_0_tex); + } else { + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + } } + uniforms.push_back(u); } - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 4; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { - if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { - u.append_id(rb->sdfgi->cascades[j].light_aniso_1_tex); + { + RD::Uniform u; + u.binding = 4; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) { + if (rb->sdfgi && j < rb->sdfgi->cascades.size()) { + u.append_id(rb->sdfgi->cascades[j].light_aniso_1_tex); + } else { + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + } + } + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 5; + if (rb->sdfgi) { + u.append_id(rb->sdfgi->occlusion_texture); } else { u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); } + uniforms.push_back(u); } - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 5; - if (rb->sdfgi) { - u.append_id(rb->sdfgi->occlusion_texture); - } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE)); + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 6; + u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 7; + u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + uniforms.push_back(u); } - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 6; - u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 7; - u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 9; - u.append_id(rb->ambient_buffer); - uniforms.push_back(u); - } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 9; + u.append_id(rb->rbgi.ambient_slice[v]); + uniforms.push_back(u); + } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 10; - u.append_id(rb->reflection_buffer); - uniforms.push_back(u); - } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 10; + u.append_id(rb->rbgi.reflection_slice[v]); + uniforms.push_back(u); + } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 11; - if (rb->sdfgi) { - u.append_id(rb->sdfgi->lightprobe_texture); - } else { - u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE)); + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 11; + if (rb->sdfgi) { + u.append_id(rb->sdfgi->lightprobe_texture); + } else { + u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE)); + } + uniforms.push_back(u); } - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 12; - u.append_id(rb->depth_texture); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 13; - u.append_id(p_normal_roughness_buffer); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 14; - RID buffer = p_voxel_gi_buffer.is_valid() ? p_voxel_gi_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); - u.append_id(buffer); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 15; - u.append_id(sdfgi_ubo); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 16; - u.append_id(rb->gi.voxel_gi_buffer); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 17; - for (int i = 0; i < MAX_VOXEL_GI_INSTANCES; i++) { - u.append_id(rb->gi.voxel_gi_textures[i]); + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 12; + u.append_id(rb->views[v].view_depth); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 13; + u.append_id(p_normal_roughness_slices[v]); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 14; + RID buffer = p_voxel_gi_buffer.is_valid() ? p_voxel_gi_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK); + u.append_id(buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 15; + u.append_id(sdfgi_ubo); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 16; + u.append_id(rb->rbgi.voxel_gi_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 17; + for (int i = 0; i < MAX_VOXEL_GI_INSTANCES; i++) { + u.append_id(rb->rbgi.voxel_gi_textures[i]); + } + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 18; + u.append_id(rb->rbgi.scene_data_ubo); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 19; + RID buffer = p_vrs_slices[v].is_valid() ? p_vrs_slices[v] : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_VRS); + u.append_id(buffer); + uniforms.push_back(u); } - uniforms.push_back(u); - } - rb->gi.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.version_get_shader(shader_version, 0), 0); - } + rb->rbgi.uniform_set[v] = RD::get_singleton()->uniform_set_create(uniforms, shader.version_get_shader(shader_version, 0), 0); + } - Mode mode; + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipelines[pipeline_specialization][mode]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->rbgi.uniform_set[v], 0); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant)); - if (rb->gi.using_half_size_gi) { - mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_HALF_RES_COMBINED : (use_sdfgi ? MODE_HALF_RES_SDFGI : MODE_HALF_RES_VOXEL_GI); - } else { - mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_COMBINED : (use_sdfgi ? MODE_SDFGI : MODE_VOXEL_GI); + if (rb->rbgi.using_half_size_gi) { + RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width >> 1, rb->internal_height >> 1, 1); + } else { + RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width, rb->internal_height, 1); + } } - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(true); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipelines[mode]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->gi.uniform_set, 0); - RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant)); - - if (rb->gi.using_half_size_gi) { - RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width >> 1, rb->internal_height >> 1, 1); - } else { - RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width, rb->internal_height, 1); - } //do barrier later to allow oeverlap //RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //no barriers, let other compute, raster and transfer happen at the same time RD::get_singleton()->draw_command_end_label(); } -RID RendererSceneGIRD::voxel_gi_instance_create(RID p_base) { +RID GI::voxel_gi_instance_create(RID p_base) { VoxelGIInstance voxel_gi; voxel_gi.gi = this; - voxel_gi.storage = storage; voxel_gi.probe = p_base; RID rid = voxel_gi_instance_owner.make_rid(voxel_gi); return rid; } -void RendererSceneGIRD::voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) { +void GI::voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) { VoxelGIInstance *voxel_gi = get_probe_instance(p_probe); ERR_FAIL_COND(!voxel_gi); voxel_gi->transform = p_xform; } -bool RendererSceneGIRD::voxel_gi_needs_update(RID p_probe) const { +bool GI::voxel_gi_needs_update(RID p_probe) const { VoxelGIInstance *voxel_gi = get_probe_instance(p_probe); ERR_FAIL_COND_V(!voxel_gi, false); - return voxel_gi->last_probe_version != storage->voxel_gi_get_version(voxel_gi->probe); + return voxel_gi->last_probe_version != voxel_gi_get_version(voxel_gi->probe); } -void RendererSceneGIRD::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) { +void GI::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) { VoxelGIInstance *voxel_gi = get_probe_instance(p_probe); ERR_FAIL_COND(!voxel_gi); voxel_gi->update(p_update_light_instances, p_light_instances, p_dynamic_objects, p_scene_render); } -void RendererSceneGIRD::debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) { +void GI::debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) { VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_voxel_gi); ERR_FAIL_COND(!voxel_gi); diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h b/servers/rendering/renderer_rd/environment/gi.h index 122644498b..ac41ad20e1 100644 --- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h +++ b/servers/rendering/renderer_rd/environment/gi.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* renderer_scene_gi_rd.h */ +/* gi.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,33 +28,73 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef RENDERING_SERVER_SCENE_GI_RD_H -#define RENDERING_SERVER_SCENE_GI_RD_H +#ifndef GI_RD_H +#define GI_RD_H #include "core/templates/local_vector.h" #include "core/templates/rid_owner.h" +#include "servers/rendering/environment/renderer_gi.h" #include "servers/rendering/renderer_compositor.h" #include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h" #include "servers/rendering/renderer_rd/renderer_scene_sky_rd.h" -#include "servers/rendering/renderer_rd/renderer_storage_rd.h" -#include "servers/rendering/renderer_rd/shaders/gi.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/sdfgi_debug.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/voxel_gi.glsl.gen.h" -#include "servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/environment/gi.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/environment/sdfgi_debug_probes.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/environment/sdfgi_integrate.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/environment/voxel_gi.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/environment/voxel_gi_debug.glsl.gen.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" +#include "servers/rendering/storage/utilities.h" // Forward declare RenderDataRD and RendererSceneRenderRD so we can pass it into some of our methods, these classes are pretty tightly bound struct RenderDataRD; class RendererSceneRenderRD; -class RendererSceneGIRD { +namespace RendererRD { + +class GI : public RendererGI { +public: + /* VOXEL GI STORAGE */ + + struct VoxelGI { + RID octree_buffer; + RID data_buffer; + RID sdf_texture; + + uint32_t octree_buffer_size = 0; + uint32_t data_buffer_size = 0; + + Vector<int> level_counts; + + int cell_count = 0; + + Transform3D to_cell_xform; + AABB bounds; + Vector3i octree_size; + + float dynamic_range = 2.0; + float energy = 1.0; + float bias = 1.4; + float normal_bias = 0.0; + float propagation = 0.7; + bool interior = false; + bool use_two_bounces = false; + + uint32_t version = 1; + uint32_t data_version = 1; + + Dependency dependency; + }; + private: - RendererStorageRD *storage = nullptr; + static GI *singleton; + + /* VOXEL GI STORAGE */ + + mutable RID_Owner<VoxelGI, true> voxel_gi_owner; /* VOXEL_GI INSTANCE */ @@ -196,10 +236,13 @@ private: uint32_t use_occlusion; float y_mult; - float cam_extent[3]; uint32_t probe_axis_size; + float z_near; + float reserved1; + float reserved2; float cam_transform[16]; + float inv_projection[16]; }; SdfgiDebugShaderRD debug; @@ -209,13 +252,17 @@ private: enum ProbeDebugMode { PROBE_DEBUG_PROBES, + PROBE_DEBUG_PROBES_MULTIVIEW, PROBE_DEBUG_VISIBILITY, + PROBE_DEBUG_VISIBILITY_MULTIVIEW, PROBE_DEBUG_MAX }; - struct DebugProbesPushConstant { - float projection[16]; + struct DebugProbesSceneData { + float projection[2][16]; + }; + struct DebugProbesPushConstant { uint32_t band_power; uint32_t sections_in_band; uint32_t band_mask; @@ -324,14 +371,64 @@ private: } sdfgi_shader; public: + static GI *get_singleton() { return singleton; } + + /* VOXEL GI API */ + + VoxelGI *get_voxel_gi(RID p_rid) { return voxel_gi_owner.get_or_null(p_rid); }; + bool owns_voxel_gi(RID p_rid) { return voxel_gi_owner.owns(p_rid); }; + + virtual RID voxel_gi_allocate() override; + virtual void voxel_gi_free(RID p_voxel_gi) override; + virtual void voxel_gi_initialize(RID p_voxel_gi) override; + + virtual void voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) override; + + virtual AABB voxel_gi_get_bounds(RID p_voxel_gi) const override; + virtual Vector3i voxel_gi_get_octree_size(RID p_voxel_gi) const override; + virtual Vector<uint8_t> voxel_gi_get_octree_cells(RID p_voxel_gi) const override; + virtual Vector<uint8_t> voxel_gi_get_data_cells(RID p_voxel_gi) const override; + virtual Vector<uint8_t> voxel_gi_get_distance_field(RID p_voxel_gi) const override; + + virtual Vector<int> voxel_gi_get_level_counts(RID p_voxel_gi) const override; + virtual Transform3D voxel_gi_get_to_cell_xform(RID p_voxel_gi) const override; + + virtual void voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) override; + virtual float voxel_gi_get_dynamic_range(RID p_voxel_gi) const override; + + virtual void voxel_gi_set_propagation(RID p_voxel_gi, float p_range) override; + virtual float voxel_gi_get_propagation(RID p_voxel_gi) const override; + + virtual void voxel_gi_set_energy(RID p_voxel_gi, float p_energy) override; + virtual float voxel_gi_get_energy(RID p_voxel_gi) const override; + + virtual void voxel_gi_set_bias(RID p_voxel_gi, float p_bias) override; + virtual float voxel_gi_get_bias(RID p_voxel_gi) const override; + + virtual void voxel_gi_set_normal_bias(RID p_voxel_gi, float p_range) override; + virtual float voxel_gi_get_normal_bias(RID p_voxel_gi) const override; + + virtual void voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) override; + virtual bool voxel_gi_is_interior(RID p_voxel_gi) const override; + + virtual void voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) override; + virtual bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const override; + + virtual uint32_t voxel_gi_get_version(RID p_probe) const override; + uint32_t voxel_gi_get_data_version(RID p_probe); + + RID voxel_gi_get_octree_buffer(RID p_voxel_gi) const; + RID voxel_gi_get_data_buffer(RID p_voxel_gi) const; + + RID voxel_gi_get_sdf_texture(RID p_voxel_gi); + /* VOXEL_GI INSTANCE */ //@TODO VoxelGIInstance is still directly used in the render code, we'll address this when we refactor the render code itself. struct VoxelGIInstance { // access to our containers - RendererStorageRD *storage = nullptr; - RendererSceneGIRD *gi = nullptr; + GI *gi = nullptr; RID probe; RID texture; @@ -444,7 +541,8 @@ public: Vector3i dirty_regions; //(0,0,0 is not dirty, negative is refresh from the end, DIRTY_ALL is refresh all. RID sdf_store_uniform_set; - RID sdf_direct_light_uniform_set; + RID sdf_direct_light_static_uniform_set; + RID sdf_direct_light_dynamic_uniform_set; RID scroll_uniform_set; RID scroll_occlusion_uniform_set; RID integrate_uniform_set; @@ -454,8 +552,7 @@ public: }; // access to our containers - RendererStorageRD *storage = nullptr; - RendererSceneGIRD *gi = nullptr; + GI *gi = nullptr; // used for rendering (voxelization) RID render_albedo; @@ -497,7 +594,8 @@ public: float min_cell_size = 0; uint32_t probe_axis_count = 0; //amount of probes per axis, this is an odd number because it encloses endpoints - RID debug_uniform_set; + RID debug_uniform_set[RendererSceneRender::MAX_RENDER_VIEWS]; + RID debug_probes_scene_data_ubo; RID debug_probes_uniform_set; RID cascades_ubo; @@ -516,7 +614,7 @@ public: int32_t cascade_dynamic_light_count[SDFGI::MAX_CASCADES]; //used dynamically RID integrate_sky_uniform_set; - void create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, RendererSceneGIRD *p_gi); + void create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, GI *p_gi); void erase(); void update(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position); void update_light(); @@ -525,8 +623,8 @@ public: int get_pending_region_data(int p_region, Vector3i &r_local_offset, Vector3i &r_local_size, AABB &r_bounds) const; void update_cascades(); - void debug_draw(const CameraMatrix &p_projection, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture); - void debug_probes(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform); + void debug_draw(uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture, const Vector<RID> &p_texture_views); + void debug_probes(RID p_framebuffer, const uint32_t p_view_count, const CameraMatrix *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth); void pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data, RendererSceneRenderRD *p_scene_render); void render_region(RID p_render_buffers, int p_region, const PagedArray<RendererSceneRender::GeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render); @@ -561,8 +659,18 @@ public: RID full_dispatch; RID full_mask; - RID uniform_set; + /* GI buffers */ + RID ambient_buffer; + RID ambient_slice[RendererSceneRender::MAX_RENDER_VIEWS]; + RID reflection_buffer; + RID reflection_slice[RendererSceneRender::MAX_RENDER_VIEWS]; bool using_half_size_gi = false; + uint32_t view_count = 1; + + RID uniform_set[RendererSceneRender::MAX_RENDER_VIEWS]; + RID scene_data_ubo; + + void free(); }; struct SDFGIData { @@ -611,49 +719,63 @@ public: uint32_t mipmaps; // 4 - 96 }; - struct PushConstant { - int32_t screen_size[2]; - float z_near; - float z_far; + struct SceneData { + float inv_projection[2][16]; + float cam_transform[16]; + float eye_offset[2][4]; - float proj_info[4]; + int32_t screen_size[2]; + float pad1; + float pad2; + }; + struct PushConstant { uint32_t max_voxel_gi_instances; uint32_t high_quality_vct; uint32_t orthogonal; - uint32_t pad; + uint32_t view_index; + + float proj_info[4]; - float cam_rotation[12]; + float z_near; + float z_far; + float pad2; + float pad3; }; RID sdfgi_ubo; + enum Mode { MODE_VOXEL_GI, MODE_SDFGI, MODE_COMBINED, - MODE_HALF_RES_VOXEL_GI, - MODE_HALF_RES_SDFGI, - MODE_HALF_RES_COMBINED, MODE_MAX }; + enum ShaderSpecializations { + SHADER_SPECIALIZATION_HALF_RES = 1 << 0, + SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX = 1 << 1, + SHADER_SPECIALIZATION_USE_VRS = 1 << 2, + SHADER_SPECIALIZATION_VARIATIONS = 0x07, + }; + RID default_voxel_gi_buffer; bool half_resolution = false; GiShaderRD shader; RID shader_version; - RID pipelines[MODE_MAX]; + RID pipelines[SHADER_SPECIALIZATION_VARIATIONS][MODE_MAX]; - RendererSceneGIRD(); - ~RendererSceneGIRD(); + GI(); + ~GI(); - void init(RendererStorageRD *p_storage, RendererSceneSkyRD *p_sky); + void init(RendererSceneSkyRD *p_sky); void free(); SDFGI *create_sdfgi(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size); void setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render); - void process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render); + void process_gi(RID p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices, RID p_environment, uint32_t p_view_count, const CameraMatrix *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render); RID voxel_gi_instance_create(RID p_base); void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform); @@ -662,4 +784,6 @@ public: void debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha); }; -#endif /* !RENDERING_SERVER_SCENE_GI_RD_H */ +} // namespace RendererRD + +#endif /* !GI_RD_H */ 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 4bfaad9fe6..85652a041d 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -30,6 +30,7 @@ #include "render_forward_clustered.h" #include "core/config/project_settings.h" +#include "servers/rendering/renderer_rd/renderer_compositor_rd.h" #include "servers/rendering/renderer_rd/storage_rd/light_storage.h" #include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h" #include "servers/rendering/renderer_rd/storage_rd/particles_storage.h" @@ -48,6 +49,13 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular() if (!specular.is_valid()) { RD::TextureFormat tf; tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + if (view_count > 1) { + tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + tf.array_layers = view_count; + } else { + tf.texture_type = RD::TEXTURE_TYPE_2D; + tf.array_layers = 1; + } tf.width = width; tf.height = height; tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; @@ -64,7 +72,7 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular() Vector<RID> fb; fb.push_back(specular); - specular_only_fb = RD::get_singleton()->framebuffer_create(fb); + specular_only_fb = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, view_count); } } else { @@ -76,15 +84,43 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular() Vector<RID> fb; fb.push_back(specular_msaa); - specular_only_fb = RD::get_singleton()->framebuffer_create(fb); + specular_only_fb = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, view_count); } } } } +void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_velocity() { + if (!velocity_buffer.is_valid()) { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R16G16_SFLOAT; + tf.width = width; + tf.height = height; + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + + if (msaa != RS::VIEWPORT_MSAA_DISABLED) { + RD::TextureFormat tf_aa = tf; + tf_aa.samples = texture_samples; + tf_aa.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + velocity_buffer_msaa = RD::get_singleton()->texture_create(tf_aa, RD::TextureView()); + + tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + } + + velocity_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); + } +} + void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_voxelgi() { if (!voxelgi_buffer.is_valid()) { RD::TextureFormat tf; + if (view_count > 1) { + tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + tf.array_layers = view_count; + } else { + tf.texture_type = RD::TEXTURE_TYPE_2D; + tf.array_layers = 1; + } tf.format = RD::DATA_FORMAT_R8G8_UINT; tf.width = width; tf.height = height; @@ -95,6 +131,14 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_voxelgi() tf_aa.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; tf_aa.samples = texture_samples; voxelgi_buffer_msaa = RD::get_singleton()->texture_create(tf_aa, RD::TextureView()); + + if (view_count == 1) { + voxelgi_msaa_views[0] = voxelgi_buffer_msaa; + } else { + for (uint32_t v = 0; v < view_count; v++) { + voxelgi_msaa_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), voxelgi_buffer_msaa, v, 0); + } + } } else { tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; } @@ -103,6 +147,14 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_voxelgi() voxelgi_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); + if (view_count == 1) { + voxelgi_views[0] = voxelgi_buffer; + } else { + for (uint32_t v = 0; v < view_count; v++) { + voxelgi_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), voxelgi_buffer, v, 0); + } + } + Vector<RID> fb; if (msaa != RS::VIEWPORT_MSAA_DISABLED) { fb.push_back(depth_msaa); @@ -114,11 +166,24 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_voxelgi() fb.push_back(voxelgi_buffer); } - depth_normal_roughness_voxelgi_fb = RD::get_singleton()->framebuffer_create(fb); + depth_normal_roughness_voxelgi_fb = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, view_count); } } void RenderForwardClustered::RenderBufferDataForwardClustered::clear() { + // note, slices are freed automatically when the parent texture is freed so we just clear them. + for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) { + color_views[v] = RID(); + depth_views[v] = RID(); + color_msaa_views[v] = RID(); + depth_msaa_views[v] = RID(); + normal_roughness_views[v] = RID(); + normal_roughness_msaa_views[v] = RID(); + voxelgi_views[v] = RID(); + voxelgi_msaa_views[v] = RID(); + vrs_views[v] = RID(); + } + if (voxelgi_buffer != RID()) { RD::get_singleton()->free(voxelgi_buffer); voxelgi_buffer = RID(); @@ -151,6 +216,7 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() { } color = RID(); + color_only_fb = RID(); depth = RID(); depth_fb = RID(); @@ -158,23 +224,37 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::clear() { if (normal_roughness_buffer.is_valid()) { RD::get_singleton()->free(normal_roughness_buffer); + normal_roughness_buffer = RID(); + if (normal_roughness_buffer_msaa.is_valid()) { RD::get_singleton()->free(normal_roughness_buffer_msaa); normal_roughness_buffer_msaa = RID(); } - normal_roughness_buffer = RID(); + depth_normal_roughness_fb = RID(); } if (!render_sdfgi_uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(render_sdfgi_uniform_set)) { RD::get_singleton()->free(render_sdfgi_uniform_set); } + + if (velocity_buffer != RID()) { + RD::get_singleton()->free(velocity_buffer); + velocity_buffer = RID(); + } + + if (velocity_buffer_msaa != RID()) { + RD::get_singleton()->free(velocity_buffer_msaa); + velocity_buffer_msaa = RID(); + } } -void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) { +void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture) { clear(); msaa = p_msaa; + use_taa = p_use_taa; + vrs = p_vrs_texture; width = p_width; height = p_height; @@ -183,11 +263,26 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c color = p_color_buffer; depth = p_depth_buffer; + if (vrs.is_valid()) { + if (view_count == 1) { + // just reuse + vrs_views[0] = vrs; + } else { + // create slices + for (uint32_t v = 0; v < view_count; v++) { + vrs_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), vrs, v, 0); + } + } + } + if (p_msaa == RS::VIEWPORT_MSAA_DISABLED) { { Vector<RID> fb; fb.push_back(p_color_buffer); fb.push_back(depth); + if (vrs.is_valid()) { + fb.push_back(vrs); + } color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count); } @@ -222,15 +317,34 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c color_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView()); - tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT; + tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT; tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; depth_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView()); + if (view_count == 1) { + // just reuse + color_views[0] = color; + depth_views[0] = depth; + color_msaa_views[0] = color_msaa; + depth_msaa_views[0] = depth_msaa; + } else { + // create slices + for (uint32_t v = 0; v < view_count; v++) { + color_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), color, v, 0); + depth_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), depth, v, 0); + color_msaa_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), color_msaa, v, 0); + depth_msaa_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), depth_msaa, v, 0); + } + } + { Vector<RID> fb; fb.push_back(color_msaa); fb.push_back(depth_msaa); + if (vrs.is_valid()) { + fb.push_back(vrs); + } color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count); } @@ -260,8 +374,19 @@ RID RenderForwardClustered::RenderBufferDataForwardClustered::get_color_pass_fb( fb.push_back(RID()); } + if (p_color_pass_flags & COLOR_PASS_FLAG_MOTION_VECTORS) { + ensure_velocity(); + fb.push_back(use_msaa ? velocity_buffer_msaa : velocity_buffer); + } else { + fb.push_back(RID()); + } + fb.push_back(use_msaa ? depth_msaa : depth); + if (vrs.is_valid()) { + fb.push_back(vrs); + } + int v_count = (p_color_pass_flags & COLOR_PASS_FLAG_MULTIVIEW) ? view_count : 1; RID framebuffer = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, v_count); color_framebuffers[p_color_pass_flags] = framebuffer; @@ -269,6 +394,8 @@ RID RenderForwardClustered::RenderBufferDataForwardClustered::get_color_pass_fb( } void RenderForwardClustered::_allocate_normal_roughness_texture(RenderBufferDataForwardClustered *rb) { + ERR_FAIL_COND_MSG(rb->view_count > 2, "Only support up to two views for roughness texture"); + if (rb->normal_roughness_buffer.is_valid()) { return; } @@ -277,10 +404,17 @@ void RenderForwardClustered::_allocate_normal_roughness_texture(RenderBufferData tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; tf.width = rb->width; tf.height = rb->height; + if (rb->view_count > 1) { + tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + tf.array_layers = rb->view_count; + } else { + tf.texture_type = RD::TEXTURE_TYPE_2D; + tf.array_layers = 1; + } tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) { - tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; } else { tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; } @@ -291,16 +425,30 @@ void RenderForwardClustered::_allocate_normal_roughness_texture(RenderBufferData Vector<RID> fb; fb.push_back(rb->depth); fb.push_back(rb->normal_roughness_buffer); - rb->depth_normal_roughness_fb = RD::get_singleton()->framebuffer_create(fb); + rb->depth_normal_roughness_fb = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, rb->view_count); } else { - tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; tf.samples = rb->texture_samples; rb->normal_roughness_buffer_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView()); Vector<RID> fb; fb.push_back(rb->depth_msaa); fb.push_back(rb->normal_roughness_buffer_msaa); - rb->depth_normal_roughness_fb = RD::get_singleton()->framebuffer_create(fb); + rb->depth_normal_roughness_fb = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, rb->view_count); + } + + if (rb->view_count == 1) { + rb->normal_roughness_views[0] = rb->normal_roughness_buffer; + if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) { + rb->normal_roughness_msaa_views[0] = rb->normal_roughness_buffer_msaa; + } + } else { + for (uint32_t v = 0; v < rb->view_count; v++) { + rb->normal_roughness_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->normal_roughness_buffer, v, 0); + if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) { + rb->normal_roughness_msaa_views[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->normal_roughness_buffer_msaa, v, 0); + } + } } } @@ -445,6 +593,10 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR; } + if constexpr ((p_color_pass_flags & COLOR_PASS_FLAG_MOTION_VECTORS) != 0) { + pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS; + } + if constexpr ((p_color_pass_flags & COLOR_PASS_FLAG_TRANSPARENT) != 0) { pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_TRANSPARENT; } @@ -460,22 +612,21 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS; } break; case PASS_MODE_SHADOW_DP: { - ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for shadow DP pass"); + ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for shadow DP pass"); pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_DP; } break; case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: { - ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for depth/roughness pass"); - pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS; + pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS; } break; case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI: { - ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for voxel GI pass"); - pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI; + pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI; } break; case PASS_MODE_DEPTH_MATERIAL: { ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for material pass"); pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL; } break; case PASS_MODE_SDF: { + // Note, SDF is prepared in world space, this shouldn't be a multiview buffer even when stereoscopic rendering is used. ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for SDF pass"); pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_SDF; } break; @@ -567,9 +718,14 @@ void RenderForwardClustered::_render_list(RenderingDevice::DrawListID p_draw_lis switch (p_params->color_pass_flags) { VALID_FLAG_COMBINATION(0); VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_TRANSPARENT); + VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_TRANSPARENT | COLOR_PASS_FLAG_MULTIVIEW); + VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_TRANSPARENT | COLOR_PASS_FLAG_MOTION_VECTORS); VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_SEPARATE_SPECULAR); + VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_SEPARATE_SPECULAR | COLOR_PASS_FLAG_MULTIVIEW); + VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_SEPARATE_SPECULAR | COLOR_PASS_FLAG_MOTION_VECTORS); VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_MULTIVIEW); - VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_TRANSPARENT | COLOR_PASS_FLAG_MULTIVIEW); + VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_MULTIVIEW | COLOR_PASS_FLAG_MOTION_VECTORS); + VALID_FLAG_COMBINATION(COLOR_PASS_FLAG_MOTION_VECTORS); default: { ERR_FAIL_MSG("Invalid color pass flag combination " + itos(p_params->color_pass_flags)); } @@ -631,29 +787,38 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat //projection.flip_y(); // Vulkan and modern APIs use Y-Down CameraMatrix correction; correction.set_depth_correction(p_flip_y); + correction.add_jitter_offset(p_render_data->taa_jitter); CameraMatrix projection = correction * p_render_data->cam_projection; //store camera into ubo - RendererStorageRD::store_camera(projection, scene_state.ubo.projection_matrix); - RendererStorageRD::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix); - RendererStorageRD::store_transform(p_render_data->cam_transform, scene_state.ubo.inv_view_matrix); - RendererStorageRD::store_transform(p_render_data->cam_transform.affine_inverse(), scene_state.ubo.view_matrix); + RendererRD::MaterialStorage::store_camera(projection, scene_state.ubo.projection_matrix); + RendererRD::MaterialStorage::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix); + RendererRD::MaterialStorage::store_transform(p_render_data->cam_transform, scene_state.ubo.inv_view_matrix); + RendererRD::MaterialStorage::store_transform(p_render_data->cam_transform.affine_inverse(), scene_state.ubo.view_matrix); for (uint32_t v = 0; v < p_render_data->view_count; v++) { projection = correction * p_render_data->view_projection[v]; - RendererStorageRD::store_camera(projection, scene_state.ubo.projection_matrix_view[v]); - RendererStorageRD::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix_view[v]); + RendererRD::MaterialStorage::store_camera(projection, scene_state.ubo.projection_matrix_view[v]); + RendererRD::MaterialStorage::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix_view[v]); + + scene_state.ubo.eye_offset[v][0] = p_render_data->view_eye_offset[v].x; + scene_state.ubo.eye_offset[v][1] = p_render_data->view_eye_offset[v].y; + scene_state.ubo.eye_offset[v][2] = p_render_data->view_eye_offset[v].z; + scene_state.ubo.eye_offset[v][3] = 0.0; } + scene_state.ubo.taa_jitter[0] = p_render_data->taa_jitter.x; + scene_state.ubo.taa_jitter[1] = p_render_data->taa_jitter.y; + scene_state.ubo.z_far = p_render_data->z_far; scene_state.ubo.z_near = p_render_data->z_near; scene_state.ubo.pancake_shadows = p_pancake_shadows; - RendererStorageRD::store_soft_shadow_kernel(directional_penumbra_shadow_kernel_get(), scene_state.ubo.directional_penumbra_shadow_kernel); - RendererStorageRD::store_soft_shadow_kernel(directional_soft_shadow_kernel_get(), scene_state.ubo.directional_soft_shadow_kernel); - RendererStorageRD::store_soft_shadow_kernel(penumbra_shadow_kernel_get(), scene_state.ubo.penumbra_shadow_kernel); - RendererStorageRD::store_soft_shadow_kernel(soft_shadow_kernel_get(), scene_state.ubo.soft_shadow_kernel); + RendererRD::MaterialStorage::store_soft_shadow_kernel(directional_penumbra_shadow_kernel_get(), scene_state.ubo.directional_penumbra_shadow_kernel); + RendererRD::MaterialStorage::store_soft_shadow_kernel(directional_soft_shadow_kernel_get(), scene_state.ubo.directional_soft_shadow_kernel); + RendererRD::MaterialStorage::store_soft_shadow_kernel(penumbra_shadow_kernel_get(), scene_state.ubo.penumbra_shadow_kernel); + RendererRD::MaterialStorage::store_soft_shadow_kernel(soft_shadow_kernel_get(), scene_state.ubo.soft_shadow_kernel); Size2 screen_pixel_size = Vector2(1.0, 1.0) / Size2(p_screen_size); scene_state.ubo.screen_pixel_size[0] = screen_pixel_size.x; @@ -708,61 +873,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat } } } -#if 0 - if (p_render_data->render_buffers.is_valid() && render_buffers_is_sdfgi_enabled(p_render_data->render_buffers)) { - scene_state.ubo.sdfgi_cascade_count = render_buffers_get_sdfgi_cascade_count(p_render_data->render_buffers); - scene_state.ubo.sdfgi_probe_axis_size = render_buffers_get_sdfgi_cascade_probe_count(p_render_data->render_buffers); - scene_state.ubo.sdfgi_cascade_probe_size[0] = scene_state.ubo.sdfgi_probe_axis_size - 1; //float version for performance - scene_state.ubo.sdfgi_cascade_probe_size[1] = scene_state.ubo.sdfgi_probe_axis_size - 1; - scene_state.ubo.sdfgi_cascade_probe_size[2] = scene_state.ubo.sdfgi_probe_axis_size - 1; - - float csize = render_buffers_get_sdfgi_cascade_size(p_render_data->render_buffers); - scene_state.ubo.sdfgi_probe_to_uvw = 1.0 / float(scene_state.ubo.sdfgi_cascade_probe_size[0]); - float occ_bias = 0.0; - scene_state.ubo.sdfgi_occlusion_bias = occ_bias / csize; - scene_state.ubo.sdfgi_use_occlusion = render_buffers_is_sdfgi_using_occlusion(p_render_data->render_buffers); - scene_state.ubo.sdfgi_energy = render_buffers_get_sdfgi_energy(p_render_data->render_buffers); - - float cascade_voxel_size = (csize / scene_state.ubo.sdfgi_cascade_probe_size[0]); - float occlusion_clamp = (cascade_voxel_size - 0.5) / cascade_voxel_size; - scene_state.ubo.sdfgi_occlusion_clamp[0] = occlusion_clamp; - scene_state.ubo.sdfgi_occlusion_clamp[1] = occlusion_clamp; - scene_state.ubo.sdfgi_occlusion_clamp[2] = occlusion_clamp; - scene_state.ubo.sdfgi_normal_bias = (render_buffers_get_sdfgi_normal_bias(p_render_data->render_buffers) / csize) * scene_state.ubo.sdfgi_cascade_probe_size[0]; - - //vec2 tex_pixel_size = 1.0 / vec2(ivec2( (OCT_SIZE+2) * params.probe_axis_size * params.probe_axis_size, (OCT_SIZE+2) * params.probe_axis_size ) ); - //vec3 probe_uv_offset = (ivec3(OCT_SIZE+2,OCT_SIZE+2,(OCT_SIZE+2) * params.probe_axis_size)) * tex_pixel_size.xyx; - - uint32_t oct_size = gi.sdfgi_get_lightprobe_octahedron_size(); - - scene_state.ubo.sdfgi_lightprobe_tex_pixel_size[0] = 1.0 / ((oct_size + 2) * scene_state.ubo.sdfgi_probe_axis_size * scene_state.ubo.sdfgi_probe_axis_size); - scene_state.ubo.sdfgi_lightprobe_tex_pixel_size[1] = 1.0 / ((oct_size + 2) * scene_state.ubo.sdfgi_probe_axis_size); - scene_state.ubo.sdfgi_lightprobe_tex_pixel_size[2] = 1.0; - - scene_state.ubo.sdfgi_probe_uv_offset[0] = float(oct_size + 2) * scene_state.ubo.sdfgi_lightprobe_tex_pixel_size[0]; - scene_state.ubo.sdfgi_probe_uv_offset[1] = float(oct_size + 2) * scene_state.ubo.sdfgi_lightprobe_tex_pixel_size[1]; - scene_state.ubo.sdfgi_probe_uv_offset[2] = float((oct_size + 2) * scene_state.ubo.sdfgi_probe_axis_size) * scene_state.ubo.sdfgi_lightprobe_tex_pixel_size[0]; - - scene_state.ubo.sdfgi_occlusion_renormalize[0] = 0.5; - scene_state.ubo.sdfgi_occlusion_renormalize[1] = 1.0; - scene_state.ubo.sdfgi_occlusion_renormalize[2] = 1.0 / float(scene_state.ubo.sdfgi_cascade_count); - - for (uint32_t i = 0; i < scene_state.ubo.sdfgi_cascade_count; i++) { - SceneState::UBO::SDFGICascade &c = scene_state.ubo.sdfgi_cascades[i]; - Vector3 pos = render_buffers_get_sdfgi_cascade_offset(p_render_data->render_buffers, i); - pos -= p_render_data->cam_transform.origin; //make pos local to camera, to reduce numerical error - c.position[0] = pos.x; - c.position[1] = pos.y; - c.position[2] = pos.z; - c.to_probe = 1.0 / render_buffers_get_sdfgi_cascade_probe_size(p_render_data->render_buffers, i); - - Vector3i probe_ofs = render_buffers_get_sdfgi_cascade_probe_offset(p_render_data->render_buffers, i); - c.probe_world_offset[0] = probe_ofs.x; - c.probe_world_offset[1] = probe_ofs.y; - c.probe_world_offset[2] = probe_ofs.z; - } - } -#endif + if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) { scene_state.ubo.use_ambient_light = true; scene_state.ubo.ambient_light_color_energy[0] = 1; @@ -802,7 +913,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat Basis sky_transform = environment_get_sky_orientation(p_render_data->environment); sky_transform = sky_transform.inverse() * p_render_data->cam_transform.basis; - RendererStorageRD::store_transform_3x3(sky_transform, scene_state.ubo.radiance_inverse_xform); + RendererRD::MaterialStorage::store_transform_3x3(sky_transform, scene_state.ubo.radiance_inverse_xform); scene_state.ubo.use_ambient_cubemap = (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ambient_src == RS::ENV_AMBIENT_SOURCE_SKY; scene_state.ubo.use_ambient_light = scene_state.ubo.use_ambient_cubemap || ambient_src == RS::ENV_AMBIENT_SOURCE_COLOR; @@ -862,14 +973,41 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat scene_state.ubo.roughness_limiter_amount = screen_space_roughness_limiter_get_amount(); scene_state.ubo.roughness_limiter_limit = screen_space_roughness_limiter_get_limit(); + if (p_render_data->render_buffers.is_valid()) { + RenderBufferDataForwardClustered *render_buffers = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_data->render_buffers)); + if (render_buffers->use_taa || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) { + memcpy(&scene_state.prev_ubo, &scene_state.ubo, sizeof(SceneState::UBO)); + + CameraMatrix prev_correction; + prev_correction.set_depth_correction(true); + prev_correction.add_jitter_offset(p_render_data->prev_taa_jitter); + CameraMatrix prev_projection = prev_correction * p_render_data->prev_cam_projection; + + //store camera into ubo + RendererRD::MaterialStorage::store_camera(prev_projection, scene_state.prev_ubo.projection_matrix); + RendererRD::MaterialStorage::store_camera(prev_projection.inverse(), scene_state.prev_ubo.inv_projection_matrix); + RendererRD::MaterialStorage::store_transform(p_render_data->prev_cam_transform, scene_state.prev_ubo.inv_view_matrix); + RendererRD::MaterialStorage::store_transform(p_render_data->prev_cam_transform.affine_inverse(), scene_state.prev_ubo.view_matrix); + + for (uint32_t v = 0; v < p_render_data->view_count; v++) { + prev_projection = prev_correction * p_render_data->view_projection[v]; + RendererRD::MaterialStorage::store_camera(prev_projection, scene_state.prev_ubo.projection_matrix_view[v]); + RendererRD::MaterialStorage::store_camera(prev_projection.inverse(), scene_state.prev_ubo.inv_projection_matrix_view[v]); + } + scene_state.prev_ubo.taa_jitter[0] = p_render_data->prev_taa_jitter.x; + scene_state.prev_ubo.taa_jitter[1] = p_render_data->prev_taa_jitter.y; + scene_state.prev_ubo.time -= time_step; + } + } + if (p_index >= (int)scene_state.uniform_buffers.size()) { uint32_t from = scene_state.uniform_buffers.size(); scene_state.uniform_buffers.resize(p_index + 1); for (uint32_t i = from; i < scene_state.uniform_buffers.size(); i++) { - scene_state.uniform_buffers[i] = RD::get_singleton()->uniform_buffer_create(sizeof(SceneState::UBO)); + scene_state.uniform_buffers[i] = RD::get_singleton()->uniform_buffer_create(sizeof(SceneState::UBO) * 2); } } - RD::get_singleton()->buffer_update(scene_state.uniform_buffers[p_index], 0, sizeof(SceneState::UBO), &scene_state.ubo, RD::BARRIER_MASK_RASTER); + RD::get_singleton()->buffer_update(scene_state.uniform_buffers[p_index], 0, sizeof(SceneState::UBO) * 2, &scene_state.ubo_data, RD::BARRIER_MASK_RASTER); } void RenderForwardClustered::_update_instance_data_buffer(RenderListType p_render_list) { @@ -895,6 +1033,7 @@ void RenderForwardClustered::_fill_instance_data(RenderListType p_render_list, i if (p_render_info) { p_render_info[RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] += element_total; } + uint64_t frame = RSG::rasterizer->get_frame_number(); uint32_t repeats = 0; GeometryInstanceSurfaceDataCache *prev_surface = nullptr; for (uint32_t i = 0; i < element_total; i++) { @@ -903,10 +1042,17 @@ void RenderForwardClustered::_fill_instance_data(RenderListType p_render_list, i SceneState::InstanceData &instance_data = scene_state.instance_data[p_render_list][i + p_offset]; + if (inst->prev_transform_dirty && frame > inst->prev_transform_change_frame + 1 && inst->prev_transform_change_frame) { + inst->prev_transform = inst->transform; + inst->prev_transform_dirty = false; + } + if (inst->store_transform_cache) { - RendererStorageRD::store_transform(inst->transform, instance_data.transform); + RendererRD::MaterialStorage::store_transform(inst->transform, instance_data.transform); + RendererRD::MaterialStorage::store_transform(inst->prev_transform, instance_data.prev_transform); } else { - RendererStorageRD::store_transform(Transform3D(), instance_data.transform); + RendererRD::MaterialStorage::store_transform(Transform3D(), instance_data.transform); + RendererRD::MaterialStorage::store_transform(Transform3D(), instance_data.prev_transform); } instance_data.flags = inst->flags_cache; @@ -1230,7 +1376,7 @@ void RenderForwardClustered::_setup_lightmaps(const PagedArray<RID> &p_lightmaps Basis to_lm = lightmap_instance_get_transform(p_lightmaps[i]).basis.inverse() * p_cam_transform.basis; to_lm = to_lm.inverse().transposed(); //will transform normals - RendererStorageRD::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform); + RendererRD::MaterialStorage::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform); scene_state.lightmap_ids[i] = p_lightmaps[i]; scene_state.lightmap_has_sh[i] = RendererRD::LightStorage::get_singleton()->lightmap_uses_spherical_harmonics(lightmap); @@ -1255,10 +1401,6 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RENDER_TIMESTAMP("Setup 3D Scene"); //scene_state.ubo.subsurface_scatter_width = subsurface_scatter_size; - - Vector2 vp_he = p_render_data->cam_projection.get_viewport_half_extents(); - scene_state.ubo.viewport_size[0] = vp_he.x; - scene_state.ubo.viewport_size[1] = vp_he.y; scene_state.ubo.directional_light_count = 0; scene_state.ubo.opaque_prepass_threshold = 0.99f; @@ -1281,13 +1423,15 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co screen_size.x = render_buffer->width; screen_size.y = render_buffer->height; + if (render_buffer->use_taa || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) { + color_pass_flags |= COLOR_PASS_FLAG_MOTION_VECTORS; + } + if (p_render_data->voxel_gi_instances->size() > 0) { using_voxelgi = true; } - if (p_render_data->view_count > 1) { - depth_pass_mode = PASS_MODE_DEPTH; - } else if (!p_render_data->environment.is_valid() && using_voxelgi) { + if (!p_render_data->environment.is_valid() && using_voxelgi) { depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI; } else if (p_render_data->environment.is_valid() && (environment_is_ssr_enabled(p_render_data->environment) || environment_is_sdfgi_enabled(p_render_data->environment) || using_voxelgi)) { if (environment_is_sdfgi_enabled(p_render_data->environment)) { @@ -1350,6 +1494,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co ERR_FAIL(); //bug? } + scene_state.ubo.viewport_size[0] = screen_size.x; + scene_state.ubo.viewport_size[1] = screen_size.y; + RD::get_singleton()->draw_command_begin_label("Render Setup"); _setup_lightmaps(*p_render_data->lightmaps, p_render_data->cam_transform); @@ -1391,7 +1538,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co clear_color.r *= bg_energy; clear_color.g *= bg_energy; clear_color.b *= bg_energy; - if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) { + if ((p_render_data->render_buffers.is_valid() && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) || environment_is_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())); } @@ -1401,7 +1548,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co clear_color.r *= bg_energy; clear_color.g *= bg_energy; clear_color.b *= bg_energy; - if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) { + if ((p_render_data->render_buffers.is_valid() && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) || environment_is_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())); } @@ -1490,9 +1637,13 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co if (needs_pre_resolve) { RD::get_singleton()->barrier(RD::BARRIER_MASK_RASTER, RD::BARRIER_MASK_COMPUTE); } - storage->get_effects()->resolve_gi(render_buffer->depth_msaa, render_buffer->normal_roughness_buffer_msaa, using_voxelgi ? render_buffer->voxelgi_buffer_msaa : RID(), render_buffer->depth, render_buffer->normal_roughness_buffer, using_voxelgi ? render_buffer->voxelgi_buffer : RID(), Vector2i(render_buffer->width, render_buffer->height), texture_multisamples[render_buffer->msaa]); + for (uint32_t v = 0; v < render_buffer->view_count; v++) { + resolve_effects->resolve_gi(render_buffer->depth_msaa_views[v], render_buffer->normal_roughness_msaa_views[v], using_voxelgi ? render_buffer->voxelgi_msaa_views[v] : RID(), render_buffer->depth_views[v], render_buffer->normal_roughness_views[v], using_voxelgi ? render_buffer->voxelgi_views[v] : RID(), Vector2i(render_buffer->width, render_buffer->height), texture_multisamples[render_buffer->msaa]); + } } else if (finish_depth) { - storage->get_effects()->resolve_depth(render_buffer->depth_msaa, render_buffer->depth, Vector2i(render_buffer->width, render_buffer->height), texture_multisamples[render_buffer->msaa]); + for (uint32_t v = 0; v < render_buffer->view_count; v++) { + resolve_effects->resolve_depth(render_buffer->depth_msaa_views[v], render_buffer->depth_views[v], Vector2i(render_buffer->width, render_buffer->height), texture_multisamples[render_buffer->msaa]); + } } RD::get_singleton()->draw_command_end_label(); } @@ -1500,7 +1651,8 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co continue_depth = !finish_depth; } - _pre_opaque_render(p_render_data, using_ssao, using_ssil, using_sdfgi || using_voxelgi, render_buffer ? render_buffer->normal_roughness_buffer : RID(), render_buffer ? render_buffer->voxelgi_buffer : RID()); + RID nullrids[RendererSceneRender::MAX_RENDER_VIEWS]; + _pre_opaque_render(p_render_data, using_ssao, using_ssil, using_sdfgi || using_voxelgi, render_buffer ? render_buffer->normal_roughness_views : nullrids, render_buffer ? render_buffer->voxelgi_buffer : RID(), render_buffer ? render_buffer->vrs_views : nullrids); RD::get_singleton()->draw_command_begin_label("Render Opaque Pass"); @@ -1523,13 +1675,14 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co Vector<Color> c; { Color cc = clear_color.srgb_to_linear(); - if (using_separate_specular) { + if (using_separate_specular || render_buffer) { cc.a = 0; //subsurf scatter must be 0 } c.push_back(cc); if (render_buffer) { - c.push_back(Color(0, 0, 0, 0)); + c.push_back(Color(0, 0, 0, 0)); // Separate specular + c.push_back(Color(0, 0, 0, 0)); // Motion vectors } } @@ -1562,18 +1715,17 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co } if (debug_sdfgi_probes) { - //debug voxelgis + //debug sdfgi bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only); bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only); CameraMatrix dc; dc.set_depth_correction(true); - CameraMatrix cm = (dc * p_render_data->cam_projection) * CameraMatrix(p_render_data->cam_transform.affine_inverse()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); - RD::get_singleton()->draw_command_begin_label("Debug SDFGI"); - _debug_sdfgi_probes(p_render_data->render_buffers, draw_list, color_only_framebuffer, cm); - RD::get_singleton()->draw_command_end_label(); - RD::get_singleton()->draw_list_end(); + CameraMatrix cms[RendererSceneRender::MAX_RENDER_VIEWS]; + for (uint32_t v = 0; v < p_render_data->view_count; v++) { + cms[v] = (dc * p_render_data->view_projection[v]) * CameraMatrix(p_render_data->cam_transform.affine_inverse()); + } + _debug_sdfgi_probes(p_render_data->render_buffers, color_only_framebuffer, p_render_data->view_count, cms, will_continue_color, will_continue_depth); } if (draw_sky || draw_sky_fog_only) { @@ -1593,14 +1745,20 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co } if (render_buffer && !can_continue_color && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) { - RD::get_singleton()->texture_resolve_multisample(render_buffer->color_msaa, render_buffer->color); + // Handle views individual, might want to look at rewriting our resolve to do both layers in one pass. + for (uint32_t v = 0; v < render_buffer->view_count; v++) { + RD::get_singleton()->texture_resolve_multisample(render_buffer->color_msaa_views[v], render_buffer->color_views[v]); + } + // TODO mame this do multiview if (using_separate_specular) { RD::get_singleton()->texture_resolve_multisample(render_buffer->specular_msaa, render_buffer->specular); } } if (render_buffer && !can_continue_depth && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) { - storage->get_effects()->resolve_depth(render_buffer->depth_msaa, render_buffer->depth, Vector2i(render_buffer->width, render_buffer->height), texture_multisamples[render_buffer->msaa]); + for (uint32_t v = 0; v < render_buffer->view_count; v++) { + resolve_effects->resolve_depth(render_buffer->depth_msaa_views[v], render_buffer->depth_views[v], Vector2i(render_buffer->width, render_buffer->height), texture_multisamples[render_buffer->msaa]); + } } if (using_separate_specular) { @@ -1619,7 +1777,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co } else { //just mix specular back RENDER_TIMESTAMP("Merge Specular"); - storage->get_effects()->merge_specular(color_only_framebuffer, render_buffer->specular, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED ? RID() : render_buffer->color, RID()); + RendererCompositorRD::singleton->get_effects()->merge_specular(color_only_framebuffer, render_buffer->specular, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED ? RID() : render_buffer->color, RID()); } } @@ -1642,7 +1800,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false); { - uint32_t transparent_color_pass_flags = (color_pass_flags | COLOR_PASS_FLAG_TRANSPARENT) & ~COLOR_PASS_FLAG_SEPARATE_SPECULAR; + uint32_t transparent_color_pass_flags = (color_pass_flags | COLOR_PASS_FLAG_TRANSPARENT) & ~(COLOR_PASS_FLAG_SEPARATE_SPECULAR); RID alpha_framebuffer = render_buffer ? render_buffer->get_color_pass_fb(transparent_color_pass_flags) : color_only_framebuffer; RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR, transparent_color_pass_flags, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count); _render_list_with_threads(&render_list_params, alpha_framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ); @@ -1655,8 +1813,13 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RD::get_singleton()->draw_command_begin_label("Resolve"); if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) { - RD::get_singleton()->texture_resolve_multisample(render_buffer->color_msaa, render_buffer->color); - storage->get_effects()->resolve_depth(render_buffer->depth_msaa, render_buffer->depth, Vector2i(render_buffer->width, render_buffer->height), texture_multisamples[render_buffer->msaa]); + for (uint32_t v = 0; v < render_buffer->view_count; v++) { + RD::get_singleton()->texture_resolve_multisample(render_buffer->color_msaa_views[v], render_buffer->color_views[v]); + resolve_effects->resolve_depth(render_buffer->depth_msaa_views[v], render_buffer->depth_views[v], Vector2i(render_buffer->width, render_buffer->height), texture_multisamples[render_buffer->msaa]); + } + if (render_buffer->use_taa) { // TODO make TAA stereo capable, this will need to be handled in a separate PR + RD::get_singleton()->texture_resolve_multisample(render_buffer->velocity_buffer_msaa, render_buffer->velocity_buffer); + } } RD::get_singleton()->draw_command_end_label(); @@ -1668,6 +1831,11 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co } RD::get_singleton()->draw_command_end_label(); + if (render_buffer && render_buffer->use_taa) { + RENDER_TIMESTAMP("TAA") + _process_taa(p_render_data->render_buffers, render_buffer->velocity_buffer, p_render_data->z_near, p_render_data->z_far); + } + if (p_render_data->render_buffers.is_valid()) { _debug_draw_cluster(p_render_data->render_buffers); @@ -2000,20 +2168,20 @@ void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i to_bounds.origin = p_bounds.position; to_bounds.basis.scale(p_bounds.size); - RendererStorageRD::store_transform(to_bounds.affine_inverse() * render_data.cam_transform, scene_state.ubo.sdf_to_bounds); + RendererRD::MaterialStorage::store_transform(to_bounds.affine_inverse() * render_data.cam_transform, scene_state.ubo.sdf_to_bounds); _setup_environment(&render_data, true, Vector2(1, 1), false, Color()); RID rp_uniform_set = _setup_sdfgi_render_pass_uniform_set(p_albedo_texture, p_emission_texture, p_emission_aniso_texture, p_geom_facing_texture); - Map<Size2i, RID>::Element *E = sdfgi_framebuffer_size_cache.find(fb_size); + HashMap<Size2i, RID>::Iterator E = sdfgi_framebuffer_size_cache.find(fb_size); if (!E) { RID fb = RD::get_singleton()->framebuffer_create_empty(fb_size); E = sdfgi_framebuffer_size_cache.insert(fb_size, fb); } RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, 0, true, false, rp_uniform_set, false); - _render_list_with_threads(&render_list_params, E->get(), RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, Rect2(), sbs); + _render_list_with_threads(&render_list_params, E->value, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, Rect2(), sbs); } RD::get_singleton()->draw_command_end_label(); @@ -2594,7 +2762,13 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te RID RenderForwardClustered::_render_buffers_get_normal_texture(RID p_render_buffers) { RenderBufferDataForwardClustered *rb = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_buffers)); - return rb->normal_roughness_buffer; + return rb->msaa == RS::VIEWPORT_MSAA_DISABLED ? rb->normal_roughness_buffer : rb->normal_roughness_buffer_msaa; +} + +RID RenderForwardClustered::_render_buffers_get_velocity_texture(RID p_render_buffers) { + RenderBufferDataForwardClustered *rb = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_buffers)); + + return rb->msaa == RS::VIEWPORT_MSAA_DISABLED ? rb->velocity_buffer : rb->velocity_buffer_msaa; } RenderForwardClustered *RenderForwardClustered::singleton = nullptr; @@ -2693,7 +2867,7 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet sdcache->surface_index = p_surface; if (ginstance->data->dirty_dependencies) { - storage->base_update_dependency(p_mesh, &ginstance->data->dependency_tracker); + RSG::utilities->base_update_dependency(p_mesh, &ginstance->data->dependency_tracker); } //shadow @@ -2936,16 +3110,16 @@ void RenderForwardClustered::_update_dirty_geometry_instances() { } } -void RenderForwardClustered::_geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker) { +void RenderForwardClustered::_geometry_instance_dependency_changed(Dependency::DependencyChangedNotification p_notification, DependencyTracker *p_tracker) { switch (p_notification) { - case RendererStorage::DEPENDENCY_CHANGED_MATERIAL: - case RendererStorage::DEPENDENCY_CHANGED_MESH: - case RendererStorage::DEPENDENCY_CHANGED_PARTICLES: - case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH: - case RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA: { + case Dependency::DEPENDENCY_CHANGED_MATERIAL: + case Dependency::DEPENDENCY_CHANGED_MESH: + case Dependency::DEPENDENCY_CHANGED_PARTICLES: + case Dependency::DEPENDENCY_CHANGED_MULTIMESH: + case Dependency::DEPENDENCY_CHANGED_SKELETON_DATA: { static_cast<RenderForwardClustered *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata)); } break; - case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: { + case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: { GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_tracker->userdata); if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) { ginstance->instance_count = RendererRD::MeshStorage::get_singleton()->multimesh_get_instances_to_draw(ginstance->data->base); @@ -2956,12 +3130,12 @@ void RenderForwardClustered::_geometry_instance_dependency_changed(RendererStora } break; } } -void RenderForwardClustered::_geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker) { +void RenderForwardClustered::_geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker) { static_cast<RenderForwardClustered *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata)); } RendererSceneRender::GeometryInstance *RenderForwardClustered::geometry_instance_create(RID p_base) { - RS::InstanceType type = storage->get_base_type(p_base); + RS::InstanceType type = RSG::utilities->get_base_type(p_base); ERR_FAIL_COND_V(!((1 << type) & RS::INSTANCE_GEOMETRY_MASK), nullptr); GeometryInstanceForwardClustered *ginstance = geometry_instance_alloc.alloc(); @@ -3014,6 +3188,13 @@ void RenderForwardClustered::geometry_instance_set_mesh_instance(GeometryInstanc void RenderForwardClustered::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) { GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance); ERR_FAIL_COND(!ginstance); + + uint64_t frame = RSG::rasterizer->get_frame_number(); + if (frame != ginstance->prev_transform_change_frame) { + ginstance->prev_transform = ginstance->transform; + ginstance->prev_transform_change_frame = frame; + ginstance->prev_transform_dirty = true; + } ginstance->transform = p_transform; ginstance->mirror = p_transform.basis.determinant() < 0; ginstance->data->aabb = p_aabb; @@ -3218,8 +3399,7 @@ void RenderForwardClustered::_update_shader_quality_settings() { _base_uniforms_changed(); //also need this } -RenderForwardClustered::RenderForwardClustered(RendererStorageRD *p_storage) : - RendererSceneRenderRD(p_storage) { +RenderForwardClustered::RenderForwardClustered() { singleton = this; /* SCENE SHADER */ @@ -3251,15 +3431,22 @@ RenderForwardClustered::RenderForwardClustered(RendererStorageRD *p_storage) : defines += "\n#define MATERIAL_UNIFORM_SET " + itos(MATERIAL_UNIFORM_SET) + "\n"; } - scene_shader.init(p_storage, defines); + scene_shader.init(defines); } render_list_thread_threshold = GLOBAL_GET("rendering/limits/forward_renderer/threaded_render_minimum_instances"); _update_shader_quality_settings(); + + resolve_effects = memnew(RendererRD::Resolve()); } RenderForwardClustered::~RenderForwardClustered() { + if (resolve_effects != nullptr) { + memdelete(resolve_effects); + resolve_effects = nullptr; + } + directional_shadow_atlas_set_size(0); { @@ -3276,8 +3463,8 @@ RenderForwardClustered::~RenderForwardClustered() { memdelete_arr(scene_state.lightmap_captures); } - while (sdfgi_framebuffer_size_cache.front()) { - RD::get_singleton()->free(sdfgi_framebuffer_size_cache.front()->get()); - sdfgi_framebuffer_size_cache.erase(sdfgi_framebuffer_size_cache.front()); + while (sdfgi_framebuffer_size_cache.begin()) { + RD::get_singleton()->free(sdfgi_framebuffer_size_cache.begin()->value); + sdfgi_framebuffer_size_cache.remove(sdfgi_framebuffer_size_cache.begin()); } } 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 0e588aecb4..ff712a20a1 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -32,11 +32,12 @@ #define RENDERING_SERVER_SCENE_RENDER_FORWARD_CLUSTERED_H #include "core/templates/paged_allocator.h" +#include "servers/rendering/renderer_rd/effects/resolve.h" #include "servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h" #include "servers/rendering/renderer_rd/pipeline_cache_rd.h" #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" -#include "servers/rendering/renderer_rd/renderer_storage_rd.h" #include "servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/utilities.h" namespace RendererSceneRenderImplementation { @@ -72,7 +73,6 @@ class RenderForwardClustered : public RendererSceneRenderRD { RENDER_LIST_ALPHA, //used for transparent objects RENDER_LIST_SECONDARY, //used for shadows and other objects RENDER_LIST_MAX - }; /* Scene Shader */ @@ -89,31 +89,48 @@ class RenderForwardClustered : public RendererSceneRenderRD { RID specular; RID normal_roughness_buffer; RID voxelgi_buffer; + RID velocity_buffer; RS::ViewportMSAA msaa; RD::TextureSamples texture_samples; + bool use_taa; RID color_msaa; RID depth_msaa; RID specular_msaa; RID normal_roughness_buffer_msaa; - RID roughness_buffer_msaa; RID voxelgi_buffer_msaa; + RID velocity_buffer_msaa; RID depth_fb; RID depth_normal_roughness_fb; RID depth_normal_roughness_voxelgi_fb; RID color_only_fb; RID specular_only_fb; + + RID vrs; + int width, height; - Map<uint32_t, RID> color_framebuffers; - uint32_t view_count; + HashMap<uint32_t, RID> color_framebuffers; + + // for multiview + uint32_t view_count = 1; + RID color_views[RendererSceneRender::MAX_RENDER_VIEWS]; // we should rewrite this so we get access to the existing views in our renderer, something we can address when we reorg this + RID depth_views[RendererSceneRender::MAX_RENDER_VIEWS]; // we should rewrite this so we get access to the existing views in our renderer, something we can address when we reorg this + RID color_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS]; + RID depth_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS]; + RID normal_roughness_views[RendererSceneRender::MAX_RENDER_VIEWS]; + RID normal_roughness_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS]; + RID voxelgi_views[RendererSceneRender::MAX_RENDER_VIEWS]; + RID voxelgi_msaa_views[RendererSceneRender::MAX_RENDER_VIEWS]; + RID vrs_views[RendererSceneRender::MAX_RENDER_VIEWS]; RID render_sdfgi_uniform_set; void ensure_specular(); void ensure_voxelgi(); + void ensure_velocity(); void clear(); - virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count); + virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture); RID get_color_pass_fb(uint32_t p_color_pass_flags); ~RenderBufferDataForwardClustered(); @@ -128,6 +145,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { virtual void _base_uniforms_changed() override; virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) override; + virtual RID _render_buffers_get_velocity_texture(RID p_render_buffers) override; bool base_uniform_set_updated = false; void _update_render_base_uniform_set(); @@ -148,7 +166,8 @@ class RenderForwardClustered : public RendererSceneRenderRD { enum ColorPassFlags { COLOR_PASS_FLAG_TRANSPARENT = 1 << 0, COLOR_PASS_FLAG_SEPARATE_SPECULAR = 1 << 1, - COLOR_PASS_FLAG_MULTIVIEW = 1 << 2 + COLOR_PASS_FLAG_MULTIVIEW = 1 << 2, + COLOR_PASS_FLAG_MOTION_VECTORS = 1 << 3, }; struct GeometryInstanceSurfaceDataCache; @@ -231,6 +250,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { float projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16]; float inv_projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16]; + float eye_offset[RendererSceneRender::MAX_RENDER_VIEWS][4]; float viewport_size[2]; float screen_pixel_size[2]; @@ -300,6 +320,9 @@ class RenderForwardClustered : public RendererSceneRenderRD { float reflection_multiplier; uint32_t pancake_shadows; + + float taa_jitter[2]; + uint32_t pad[2]; }; struct PushConstant { @@ -310,6 +333,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { struct InstanceData { float transform[16]; + float prev_transform[16]; uint32_t flags; uint32_t instance_uniforms_ofs; //base offset in global buffer for instance variables uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap index) @@ -317,7 +341,9 @@ class RenderForwardClustered : public RendererSceneRenderRD { float lightmap_uv_scale[4]; }; - UBO ubo; + UBO ubo_data[2]; + UBO &ubo = ubo_data[0]; + UBO &prev_ubo = ubo_data[1]; LocalVector<RID> uniform_buffers; @@ -396,7 +422,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { void _fill_instance_data(RenderListType p_render_list, int *p_render_info = nullptr, uint32_t p_offset = 0, int32_t p_max_elements = -1, bool p_update_buffer = true); void _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_using_sdfgi = false, bool p_using_opaque_gi = false, bool p_append = false); - Map<Size2i, RID> sdfgi_framebuffer_size_cache; + HashMap<Size2i, RID> sdfgi_framebuffer_size_cache; struct GeometryInstanceData; struct GeometryInstanceForwardClustered; @@ -492,7 +518,10 @@ class RenderForwardClustered : public RendererSceneRenderRD { //used during setup uint32_t base_flags = 0; + uint64_t prev_transform_change_frame = 0xFFFFFFFF; + bool prev_transform_dirty = true; Transform3D transform; + Transform3D prev_transform; RID voxel_gi_instances[MAX_VOXEL_GI_INSTANCESS_PER_INSTANCE]; RID lightmap_instance; GeometryInstanceLightmapSH *lightmap_sh = nullptr; @@ -511,12 +540,12 @@ class RenderForwardClustered : public RendererSceneRenderRD { AABB aabb; bool use_dynamic_gi = false; - bool use_baked_light = false; + bool use_baked_light = true; bool cast_double_sided_shadows = false; bool mirror = false; bool dirty_dependencies = false; - RendererStorage::DependencyTracker dependency_tracker; + DependencyTracker dependency_tracker; }; Data *data = nullptr; @@ -525,8 +554,8 @@ class RenderForwardClustered : public RendererSceneRenderRD { dirty_list_element(this) {} }; - static void _geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker); - static void _geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker); + static void _geometry_instance_dependency_changed(Dependency::DependencyChangedNotification p_notification, DependencyTracker *p_tracker); + static void _geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker); SelfList<GeometryInstanceForwardClustered>::List geometry_instance_dirty_list; @@ -603,6 +632,8 @@ class RenderForwardClustered : public RendererSceneRenderRD { virtual void _update_shader_quality_settings() override; + RendererRD::Resolve *resolve_effects = nullptr; + protected: virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override; @@ -656,7 +687,7 @@ public: virtual bool free(RID p_rid) override; - RenderForwardClustered(RendererStorageRD *p_storage); + RenderForwardClustered(); ~RenderForwardClustered(); }; } // namespace RendererSceneRenderImplementation 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 036ad0f18a..1951bfe915 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 @@ -154,7 +154,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { print_line(gen_code.defines[i]); } - Map<String, String>::Element *el = gen_code.code.front(); + RBMap<String, String>::Element *el = gen_code.code.front(); while (el) { print_line("\n**code " + el->key() + ":\n" + el->value()); @@ -235,10 +235,10 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { } } - // Color pass -> attachment 0: Color/Diffuse, attachment 1: Separate Specular + // Color pass -> attachment 0: Color/Diffuse, attachment 1: Separate Specular, attachment 2: Motion Vectors RD::PipelineColorBlendState blend_state_color_blend; - blend_state_color_blend.attachments = { blend_attachment, RD::PipelineColorBlendState::Attachment() }; - RD::PipelineColorBlendState blend_state_color_opaque = RD::PipelineColorBlendState::create_disabled(2); + blend_state_color_blend.attachments = { blend_attachment, RD::PipelineColorBlendState::Attachment(), RD::PipelineColorBlendState::Attachment() }; + RD::PipelineColorBlendState blend_state_color_opaque = RD::PipelineColorBlendState::create_disabled(3); RD::PipelineColorBlendState blend_state_depth_normal_roughness = RD::PipelineColorBlendState::create_disabled(1); RD::PipelineColorBlendState blend_state_depth_normal_roughness_giprobe = RD::PipelineColorBlendState::create_disabled(2); @@ -282,6 +282,8 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL, SHADER_VERSION_DEPTH_PASS_WITH_SDF, SHADER_VERSION_DEPTH_PASS_MULTIVIEW, + SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW, + SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW, SHADER_VERSION_COLOR_PASS, }; @@ -326,6 +328,10 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { } } + if (l & PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS) { + shader_flags |= SHADER_COLOR_PASS_FLAG_MOTION_VECTORS; + } + if (l & PIPELINE_COLOR_PASS_FLAG_LIGHTMAP) { shader_flags |= SHADER_COLOR_PASS_FLAG_LIGHTMAP; } @@ -345,9 +351,9 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) { if (k == PIPELINE_VERSION_DEPTH_PASS || k == PIPELINE_VERSION_DEPTH_PASS_DP || k == PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW) { //none, leave empty - } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) { + } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS || k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW) { blend_state = blend_state_depth_normal_roughness; - } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI) { + } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI || k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW) { blend_state = blend_state_depth_normal_roughness_giprobe; } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL) { blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way @@ -376,14 +382,14 @@ void SceneShaderForwardClustered::ShaderData::set_default_texture_param(const St } } else { if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = Map<int, RID>(); + default_texture_params[p_name] = HashMap<int, RID>(); } default_texture_params[p_name][p_index] = p_texture; } } void SceneShaderForwardClustered::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { - Map<int, StringName> order; + HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) { @@ -477,7 +483,7 @@ void SceneShaderForwardClustered::MaterialData::set_next_pass(RID p_pass) { next_pass = p_pass; } -bool SceneShaderForwardClustered::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +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, RD::BARRIER_MASK_RASTER); @@ -514,24 +520,26 @@ SceneShaderForwardClustered::~SceneShaderForwardClustered() { material_storage->material_free(default_material); } -void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const String p_defines) { +void SceneShaderForwardClustered::init(const String p_defines) { RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - storage = p_storage; { 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_GIPROBE + 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<String> color_pass_flags = { "\n#define MODE_SEPARATE_SPECULAR\n", // SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR "\n#define USE_LIGHTMAP\n", // SHADER_COLOR_PASS_FLAG_LIGHTMAP "\n#define USE_MULTIVIEW\n", // SHADER_COLOR_PASS_FLAG_MULTIVIEW + "\n#define MOTION_VECTORS\n", // SHADER_COLOR_PASS_FLAG_MOTION_VECTORS }; for (int i = 0; i < SHADER_COLOR_PASS_FLAG_COUNT; i++) { @@ -548,6 +556,8 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin if (!RendererCompositorRD::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); // TODO Add a way to enable/disable color pass flags } } @@ -557,17 +567,29 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin 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_MULTIVIEW | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP); + 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_MULTIVIEW | PIPELINE_COLOR_PASS_FLAG_LIGHTMAP); + 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); material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_shader_funcs); material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_material_funcs); @@ -604,7 +626,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin //builtins - actions.renames["TIME"] = "scene_data.time"; + actions.renames["TIME"] = "global_time"; actions.renames["PI"] = _MKSTR(Math_PI); actions.renames["TAU"] = _MKSTR(Math_TAU); actions.renames["E"] = _MKSTR(Math_E); @@ -743,7 +765,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin actions.base_texture_binding_index = 1; actions.texture_layout_set = RenderForwardClustered::MATERIAL_UNIFORM_SET; actions.base_uniform_string = "material."; - actions.base_varying_index = 10; + actions.base_varying_index = 11; actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; 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 0b2df983ff..1cfe723174 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 @@ -32,7 +32,6 @@ #define RSSR_SCENE_SHADER_FC_H #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" -#include "servers/rendering/renderer_rd/renderer_storage_rd.h" #include "servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl.gen.h" namespace RendererSceneRenderImplementation { @@ -42,8 +41,6 @@ private: static SceneShaderForwardClustered *singleton; public: - RendererStorageRD *storage = nullptr; - enum ShaderVersion { SHADER_VERSION_DEPTH_PASS, SHADER_VERSION_DEPTH_PASS_DP, @@ -52,6 +49,8 @@ public: SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL, SHADER_VERSION_DEPTH_PASS_WITH_SDF, SHADER_VERSION_DEPTH_PASS_MULTIVIEW, + SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW, + SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW, SHADER_VERSION_COLOR_PASS, SHADER_VERSION_MAX }; @@ -60,7 +59,8 @@ public: SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR = 1 << 0, SHADER_COLOR_PASS_FLAG_LIGHTMAP = 1 << 1, SHADER_COLOR_PASS_FLAG_MULTIVIEW = 1 << 2, - SHADER_COLOR_PASS_FLAG_COUNT = 1 << 3 + SHADER_COLOR_PASS_FLAG_MOTION_VECTORS = 1 << 3, + SHADER_COLOR_PASS_FLAG_COUNT = 1 << 4 }; enum PipelineVersion { @@ -71,6 +71,8 @@ public: PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL, PIPELINE_VERSION_DEPTH_PASS_WITH_SDF, PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW, + PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW, + PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW, PIPELINE_VERSION_COLOR_PASS, PIPELINE_VERSION_MAX }; @@ -80,7 +82,8 @@ public: PIPELINE_COLOR_PASS_FLAG_SEPARATE_SPECULAR = 1 << 1, PIPELINE_COLOR_PASS_FLAG_LIGHTMAP = 1 << 2, PIPELINE_COLOR_PASS_FLAG_MULTIVIEW = 1 << 3, - PIPELINE_COLOR_PASS_FLAG_COUNT = 1 << 4, + PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS = 1 << 4, + PIPELINE_COLOR_PASS_FLAG_COUNT = 1 << 5, }; enum ShaderSpecializations { @@ -138,14 +141,14 @@ public: String path; - Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; + HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<uint32_t> ubo_offsets; uint32_t ubo_size = 0; String code; - Map<StringName, Map<int, RID>> default_texture_params; + HashMap<StringName, HashMap<int, RID>> default_texture_params; DepthDraw depth_draw; DepthTest depth_test; @@ -208,7 +211,7 @@ public: uint8_t priority; virtual void set_render_priority(int p_priority); virtual void set_next_pass(RID p_pass); - virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); + virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); virtual ~MaterialData(); }; @@ -239,11 +242,11 @@ public: ShaderData *overdraw_material_shader_ptr = nullptr; Vector<RD::PipelineSpecializationConstant> default_specialization_constants; - Set<uint32_t> valid_color_pass_pipelines; + HashSet<uint32_t> valid_color_pass_pipelines; SceneShaderForwardClustered(); ~SceneShaderForwardClustered(); - void init(RendererStorageRD *p_storage, const String p_defines); + void init(const String p_defines); void set_default_specialization_constants(const Vector<RD::PipelineSpecializationConstant> &p_constants); }; 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 1cbf804ece..966621c93e 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -87,10 +87,11 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::clear() { } } -void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) { +void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture) { clear(); msaa = p_msaa; + vrs = p_vrs_texture; Size2i target_size = RD::get_singleton()->texture_size(p_target_buffer); @@ -108,6 +109,9 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b Vector<RID> fb; fb.push_back(p_color_buffer); // 0 - color buffer fb.push_back(depth); // 1 - depth buffer + if (vrs.is_valid()) { + fb.push_back(vrs); // 2 - vrs texture + } // Now define our subpasses Vector<RD::FramebufferPass> passes; @@ -116,6 +120,9 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b // re-using the same attachments pass.color_attachments.push_back(0); pass.depth_attachment = 1; + if (vrs.is_valid()) { + pass.vrs_attachment = 2; + } // - opaque pass passes.push_back(pass); @@ -131,12 +138,13 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b if (!is_scaled) { // - add blit to 2D pass - fb.push_back(p_target_buffer); // 2 - target buffer + int target_buffer_id = fb.size(); + fb.push_back(p_target_buffer); // 2/3 - target buffer RD::FramebufferPass blit_pass; - blit_pass.color_attachments.push_back(2); + blit_pass.color_attachments.push_back(target_buffer_id); blit_pass.input_attachments.push_back(0); - passes.push_back(blit_pass); + passes.push_back(blit_pass); // this doesn't need VRS color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count); } else { @@ -179,6 +187,9 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b Vector<RID> fb; fb.push_back(color_msaa); // 0 - msaa color buffer fb.push_back(depth_msaa); // 1 - msaa depth buffer + if (vrs.is_valid()) { + fb.push_back(vrs); // 2 - vrs texture + } // Now define our subpasses Vector<RD::FramebufferPass> passes; @@ -187,18 +198,22 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b // re-using the same attachments pass.color_attachments.push_back(0); pass.depth_attachment = 1; + if (vrs.is_valid()) { + pass.vrs_attachment = 2; + } // - opaque pass passes.push_back(pass); // - add sky pass - fb.push_back(color); // 2 - color buffer + int color_buffer_id = fb.size(); + fb.push_back(color); // color buffer passes.push_back(pass); // without resolve for our 3 + 4 subpass config { // but with resolve for our 2 subpass config Vector<RD::FramebufferPass> two_passes; two_passes.push_back(pass); // opaque subpass without resolve - pass.resolve_attachments.push_back(2); + pass.resolve_attachments.push_back(color_buffer_id); two_passes.push_back(pass); // sky subpass with resolve color_fbs[FB_CONFIG_TWO_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, two_passes, RenderingDevice::INVALID_ID, view_count); @@ -217,10 +232,11 @@ void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_b if (!is_scaled) { // - add blit to 2D pass - fb.push_back(p_target_buffer); // 3 - target buffer + int target_buffer_id = fb.size(); + fb.push_back(p_target_buffer); // target buffer RD::FramebufferPass blit_pass; - blit_pass.color_attachments.push_back(3); - blit_pass.input_attachments.push_back(2); + blit_pass.color_attachments.push_back(target_buffer_id); + blit_pass.input_attachments.push_back(color_buffer_id); passes.push_back(blit_pass); color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count); @@ -465,7 +481,7 @@ void RenderForwardMobile::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, c Basis to_lm = lightmap_instance_get_transform(p_lightmaps[i]).basis.inverse() * p_cam_transform.basis; to_lm = to_lm.inverse().transposed(); //will transform normals - RendererStorageRD::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform); + RendererRD::MaterialStorage::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform); scene_state.lightmap_ids[i] = p_lightmaps[i]; scene_state.lightmap_has_sh[i] = RendererRD::LightStorage::get_singleton()->lightmap_uses_spherical_harmonics(lightmap); @@ -485,9 +501,6 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color RENDER_TIMESTAMP("Setup 3D Scene"); - Vector2 vp_he = p_render_data->cam_projection.get_viewport_half_extents(); - scene_state.ubo.viewport_size[0] = vp_he.x; - scene_state.ubo.viewport_size[1] = vp_he.y; scene_state.ubo.directional_light_count = 0; scene_state.ubo.opaque_prepass_threshold = 0.0; @@ -567,6 +580,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color ERR_FAIL(); //bug? } + scene_state.ubo.viewport_size[0] = screen_size.x; + scene_state.ubo.viewport_size[1] = screen_size.y; + RD::get_singleton()->draw_command_begin_label("Render Setup"); _setup_lightmaps(*p_render_data->lightmaps, p_render_data->cam_transform); @@ -675,7 +691,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color RD::get_singleton()->draw_command_end_label(); // Setup Sky resolution buffers } - _pre_opaque_render(p_render_data, false, false, false, RID(), RID()); + RID nullrids[RendererSceneRender::MAX_RENDER_VIEWS]; + _pre_opaque_render(p_render_data, false, false, false, nullrids, RID(), nullrids); uint32_t spec_constant_base_flags = 0; @@ -1324,6 +1341,10 @@ RID RenderForwardMobile::_render_buffers_get_normal_texture(RID p_render_buffers return RID(); } +RID RenderForwardMobile::_render_buffers_get_velocity_texture(RID p_render_buffers) { + return RID(); +} + _FORCE_INLINE_ static uint32_t _indices_to_primitives(RS::PrimitiveType p_primitive, uint32_t p_indices) { static const uint32_t divisor[RS::PRIMITIVE_MAX] = { 1, 2, 1, 3, 1 }; static const uint32_t subtractor[RS::PRIMITIVE_MAX] = { 0, 0, 1, 0, 1 }; @@ -1529,15 +1550,20 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data, CameraMatrix projection = correction * p_render_data->cam_projection; //store camera into ubo - RendererStorageRD::store_camera(projection, scene_state.ubo.projection_matrix); - RendererStorageRD::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix); - RendererStorageRD::store_transform(p_render_data->cam_transform, scene_state.ubo.inv_view_matrix); - RendererStorageRD::store_transform(p_render_data->cam_transform.affine_inverse(), scene_state.ubo.view_matrix); + RendererRD::MaterialStorage::store_camera(projection, scene_state.ubo.projection_matrix); + RendererRD::MaterialStorage::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix); + RendererRD::MaterialStorage::store_transform(p_render_data->cam_transform, scene_state.ubo.inv_view_matrix); + RendererRD::MaterialStorage::store_transform(p_render_data->cam_transform.affine_inverse(), scene_state.ubo.view_matrix); for (uint32_t v = 0; v < p_render_data->view_count; v++) { projection = correction * p_render_data->view_projection[v]; - RendererStorageRD::store_camera(projection, scene_state.ubo.projection_matrix_view[v]); - RendererStorageRD::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix_view[v]); + RendererRD::MaterialStorage::store_camera(projection, scene_state.ubo.projection_matrix_view[v]); + RendererRD::MaterialStorage::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix_view[v]); + + scene_state.ubo.eye_offset[v][0] = p_render_data->view_eye_offset[v].x; + scene_state.ubo.eye_offset[v][1] = p_render_data->view_eye_offset[v].y; + scene_state.ubo.eye_offset[v][2] = p_render_data->view_eye_offset[v].z; + scene_state.ubo.eye_offset[v][3] = 0.0; } scene_state.ubo.z_far = p_render_data->z_far; @@ -1545,10 +1571,10 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data, scene_state.ubo.pancake_shadows = p_pancake_shadows; - RendererStorageRD::store_soft_shadow_kernel(directional_penumbra_shadow_kernel_get(), scene_state.ubo.directional_penumbra_shadow_kernel); - RendererStorageRD::store_soft_shadow_kernel(directional_soft_shadow_kernel_get(), scene_state.ubo.directional_soft_shadow_kernel); - RendererStorageRD::store_soft_shadow_kernel(penumbra_shadow_kernel_get(), scene_state.ubo.penumbra_shadow_kernel); - RendererStorageRD::store_soft_shadow_kernel(soft_shadow_kernel_get(), scene_state.ubo.soft_shadow_kernel); + RendererRD::MaterialStorage::store_soft_shadow_kernel(directional_penumbra_shadow_kernel_get(), scene_state.ubo.directional_penumbra_shadow_kernel); + RendererRD::MaterialStorage::store_soft_shadow_kernel(directional_soft_shadow_kernel_get(), scene_state.ubo.directional_soft_shadow_kernel); + RendererRD::MaterialStorage::store_soft_shadow_kernel(penumbra_shadow_kernel_get(), scene_state.ubo.penumbra_shadow_kernel); + RendererRD::MaterialStorage::store_soft_shadow_kernel(soft_shadow_kernel_get(), scene_state.ubo.soft_shadow_kernel); Size2 screen_pixel_size = Vector2(1.0, 1.0) / Size2(p_screen_size); scene_state.ubo.screen_pixel_size[0] = screen_pixel_size.x; @@ -1638,7 +1664,7 @@ void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data, Basis sky_transform = environment_get_sky_orientation(p_render_data->environment); sky_transform = sky_transform.inverse() * p_render_data->cam_transform.basis; - RendererStorageRD::store_transform_3x3(sky_transform, scene_state.ubo.radiance_inverse_xform); + RendererRD::MaterialStorage::store_transform_3x3(sky_transform, scene_state.ubo.radiance_inverse_xform); scene_state.ubo.use_ambient_cubemap = (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ambient_src == RS::ENV_AMBIENT_SOURCE_SKY; scene_state.ubo.use_ambient_light = scene_state.ubo.use_ambient_cubemap || ambient_src == RS::ENV_AMBIENT_SOURCE_COLOR; @@ -1856,9 +1882,9 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr GeometryInstanceForwardMobile::PushConstant push_constant; if (inst->store_transform_cache) { - RendererStorageRD::store_transform(inst->transform, push_constant.transform); + RendererRD::MaterialStorage::store_transform(inst->transform, push_constant.transform); } else { - RendererStorageRD::store_transform(Transform3D(), push_constant.transform); + RendererRD::MaterialStorage::store_transform(Transform3D(), push_constant.transform); } push_constant.flags = inst->flags_cache; @@ -2022,7 +2048,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr /* Geometry instance */ RendererSceneRender::GeometryInstance *RenderForwardMobile::geometry_instance_create(RID p_base) { - RS::InstanceType type = storage->get_base_type(p_base); + RS::InstanceType type = RSG::utilities->get_base_type(p_base); ERR_FAIL_COND_V(!((1 << type) & RS::INSTANCE_GEOMETRY_MASK), nullptr); GeometryInstanceForwardMobile *ginstance = geometry_instance_alloc.alloc(); @@ -2363,7 +2389,7 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI sdcache->surface_index = p_surface; if (ginstance->data->dirty_dependencies) { - storage->base_update_dependency(p_mesh, &ginstance->data->dependency_tracker); + RSG::utilities->base_update_dependency(p_mesh, &ginstance->data->dependency_tracker); } //shadow @@ -2599,16 +2625,16 @@ void RenderForwardMobile::_update_dirty_geometry_instances() { } } -void RenderForwardMobile::_geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker) { +void RenderForwardMobile::_geometry_instance_dependency_changed(Dependency::DependencyChangedNotification p_notification, DependencyTracker *p_tracker) { switch (p_notification) { - case RendererStorage::DEPENDENCY_CHANGED_MATERIAL: - case RendererStorage::DEPENDENCY_CHANGED_MESH: - case RendererStorage::DEPENDENCY_CHANGED_PARTICLES: - case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH: - case RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA: { + case Dependency::DEPENDENCY_CHANGED_MATERIAL: + case Dependency::DEPENDENCY_CHANGED_MESH: + case Dependency::DEPENDENCY_CHANGED_PARTICLES: + case Dependency::DEPENDENCY_CHANGED_MULTIMESH: + case Dependency::DEPENDENCY_CHANGED_SKELETON_DATA: { static_cast<RenderForwardMobile *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata)); } break; - case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: { + case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: { GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_tracker->userdata); if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) { ginstance->instance_count = RendererRD::MeshStorage::get_singleton()->multimesh_get_instances_to_draw(ginstance->data->base); @@ -2619,7 +2645,7 @@ void RenderForwardMobile::_geometry_instance_dependency_changed(RendererStorage: } break; } } -void RenderForwardMobile::_geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker) { +void RenderForwardMobile::_geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker) { static_cast<RenderForwardMobile *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata)); } @@ -2685,8 +2711,7 @@ void RenderForwardMobile::_update_shader_quality_settings() { _base_uniforms_changed(); //also need this } -RenderForwardMobile::RenderForwardMobile(RendererStorageRD *p_storage) : - RendererSceneRenderRD(p_storage) { +RenderForwardMobile::RenderForwardMobile() { singleton = this; sky.set_texture_format(_render_buffers_get_color_format()); @@ -2718,7 +2743,7 @@ RenderForwardMobile::RenderForwardMobile(RendererStorageRD *p_storage) : defines += "\n#define MATERIAL_UNIFORM_SET " + itos(MATERIAL_UNIFORM_SET) + "\n"; } - scene_shader.init(p_storage, defines); + scene_shader.init(defines); // !BAS! maybe we need a mobile version of this setting? render_list_thread_threshold = GLOBAL_GET("rendering/limits/forward_renderer/threaded_render_minimum_instances"); diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h index 0a7e973120..bf4a52d466 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -35,7 +35,7 @@ #include "servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h" #include "servers/rendering/renderer_rd/pipeline_cache_rd.h" #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" -#include "servers/rendering/renderer_rd/renderer_storage_rd.h" +#include "servers/rendering/renderer_rd/storage_rd/utilities.h" namespace RendererSceneRenderImplementation { @@ -131,12 +131,14 @@ protected: RID depth_msaa; // RID normal_roughness_buffer_msaa; + RID vrs; + RID color_fbs[FB_CONFIG_MAX]; int width, height; uint32_t view_count; void clear(); - virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count); + virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture); ~RenderBufferDataForwardMobile(); }; @@ -224,6 +226,7 @@ protected: virtual void _base_uniforms_changed() override; void _update_render_base_uniform_set(); virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) override; + virtual RID _render_buffers_get_velocity_texture(RID p_render_buffers) override; void _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_append = false); void _fill_element_info(RenderListType p_render_list, uint32_t p_offset = 0, int32_t p_max_elements = -1); @@ -259,6 +262,7 @@ protected: float projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16]; float inv_projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16]; + float eye_offset[RendererSceneRender::MAX_RENDER_VIEWS][4]; float viewport_size[2]; float screen_pixel_size[2]; @@ -589,13 +593,13 @@ protected: RID material_overlay; AABB aabb; - bool use_baked_light = false; + bool use_baked_light = true; bool cast_double_sided_shadows = false; // bool mirror = false; // !BAS! Does not seem used, we already have this in the main struct bool dirty_dependencies = false; - RendererStorage::DependencyTracker dependency_tracker; + DependencyTracker dependency_tracker; }; Data *data = nullptr; @@ -611,8 +615,8 @@ protected: public: virtual RID reflection_probe_create_framebuffer(RID p_color, RID p_depth) override; - static void _geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker); - static void _geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker); + static void _geometry_instance_dependency_changed(Dependency::DependencyChangedNotification p_notification, DependencyTracker *p_tracker); + static void _geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker); SelfList<GeometryInstanceForwardMobile>::List geometry_instance_dirty_list; @@ -666,7 +670,7 @@ public: virtual bool is_volumetric_supported() const override; virtual uint32_t get_max_elements() const override; - RenderForwardMobile(RendererStorageRD *p_storage); + RenderForwardMobile(); ~RenderForwardMobile(); }; } // namespace RendererSceneRenderImplementation 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 cdddc35579..dd00dc2bf9 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 @@ -154,7 +154,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) { print_line(gen_code.defines[i]); } - Map<String, String>::Element * el = gen_code.code.front(); + RBMap<String, String>::Element * el = gen_code.code.front(); while (el) { print_line("\n**code " + el->key() + ":\n" + el->value()); @@ -339,14 +339,14 @@ void SceneShaderForwardMobile::ShaderData::set_default_texture_param(const Strin } } else { if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = Map<int, RID>(); + default_texture_params[p_name] = HashMap<int, RID>(); } default_texture_params[p_name][p_index] = p_texture; } } void SceneShaderForwardMobile::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { - Map<int, StringName> order; + HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) { @@ -440,7 +440,7 @@ void SceneShaderForwardMobile::MaterialData::set_next_pass(RID p_pass) { next_pass = p_pass; } -bool SceneShaderForwardMobile::MaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +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, RD::BARRIER_MASK_RASTER); @@ -466,8 +466,7 @@ SceneShaderForwardMobile::SceneShaderForwardMobile() { singleton = this; } -void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p_defines) { - storage = p_storage; +void SceneShaderForwardMobile::init(const String p_defines) { RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); /* SCENE SHADER */ @@ -529,7 +528,7 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p //builtins - actions.renames["TIME"] = "scene_data.time"; + actions.renames["TIME"] = "scene_data_block.data.time"; actions.renames["PI"] = _MKSTR(Math_PI); actions.renames["TAU"] = _MKSTR(Math_TAU); actions.renames["E"] = _MKSTR(Math_E); diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h index 50b5fb26ec..88c2143b09 100644 --- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h @@ -32,7 +32,6 @@ #define RSSR_SCENE_SHADER_FM_H #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" -#include "servers/rendering/renderer_rd/renderer_storage_rd.h" #include "servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl.gen.h" namespace RendererSceneRenderImplementation { @@ -40,7 +39,6 @@ namespace RendererSceneRenderImplementation { class SceneShaderForwardMobile { private: static SceneShaderForwardMobile *singleton; - RendererStorageRD *storage = nullptr; public: enum ShaderVersion { @@ -104,14 +102,14 @@ public: String path; - Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; + HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<uint32_t> ubo_offsets; uint32_t ubo_size = 0; String code; - Map<StringName, Map<int, RID>> default_texture_params; + HashMap<StringName, HashMap<int, RID>> default_texture_params; DepthDraw depth_draw; DepthTest depth_test; @@ -171,7 +169,7 @@ public: uint8_t priority; virtual void set_render_priority(int p_priority); virtual void set_next_pass(RID p_pass); - virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); + virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); virtual ~MaterialData(); }; @@ -207,7 +205,7 @@ public: Vector<RD::PipelineSpecializationConstant> default_specialization_constants; - void init(RendererStorageRD *p_storage, const String p_defines); + void init(const String p_defines); void set_default_specialization_constants(const Vector<RD::PipelineSpecializationConstant> &p_constants); }; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 386bc18fcd..7d55be1216 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -1581,7 +1581,8 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index, //light.basis.scale(Vector3(to_light.elements[0].length(),to_light.elements[1].length(),1)); Rect2i rect((state.shadow_texture_size / 4) * i, p_shadow_index * 2, (state.shadow_texture_size / 4), 2); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect); + RD::InitialAction initial_action = i == 0 ? RD::INITIAL_ACTION_CLEAR_REGION : RD::INITIAL_ACTION_CLEAR_REGION_CONTINUE; + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, initial_action, i != 3 ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, initial_action, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect); CameraMatrix projection; { @@ -1670,7 +1671,7 @@ void RendererCanvasRenderRD::light_update_directional_shadow(RID p_rid, int p_sh cc.push_back(Color(1, 1, 1, 1)); Rect2i rect(0, p_shadow_index * 2, state.shadow_texture_size, 2); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::INITIAL_ACTION_CLEAR_REGION, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR_REGION, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect); CameraMatrix projection; projection.set_orthogonal(-half_size, half_size, -0.5, 0.5, 0.0, distance); @@ -2160,14 +2161,14 @@ void RendererCanvasRenderRD::CanvasShaderData::set_default_texture_param(const S } } else { if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = Map<int, RID>(); + default_texture_params[p_name] = HashMap<int, RID>(); } default_texture_params[p_name][p_index] = p_texture; } } void RendererCanvasRenderRD::CanvasShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { - Map<int, StringName> order; + HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) { @@ -2246,7 +2247,7 @@ RendererRD::ShaderData *RendererCanvasRenderRD::_create_shader_func() { return shader_data; } -bool RendererCanvasRenderRD::CanvasMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +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); @@ -2270,10 +2271,9 @@ void RendererCanvasRenderRD::set_time(double p_time) { void RendererCanvasRenderRD::update() { } -RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) { +RendererCanvasRenderRD::RendererCanvasRenderRD() { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - storage = p_storage; { //create default samplers @@ -2432,6 +2432,7 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) { actions.usage_defines["NORMAL"] = "#define NORMAL_USED\n"; 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.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 06970acca6..2ab5a7c831 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -34,15 +34,13 @@ #include "servers/rendering/renderer_canvas_render.h" #include "servers/rendering/renderer_compositor.h" #include "servers/rendering/renderer_rd/pipeline_cache_rd.h" -#include "servers/rendering/renderer_rd/renderer_storage_rd.h" #include "servers/rendering/renderer_rd/shaders/canvas.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/canvas_occlusion.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" #include "servers/rendering/rendering_device.h" #include "servers/rendering/shader_compiler.h" class RendererCanvasRenderRD : public RendererCanvasRender { - RendererStorageRD *storage = nullptr; - enum { BASE_UNIFORM_SET = 0, MATERIAL_UNIFORM_SET = 1, @@ -166,14 +164,14 @@ class RendererCanvasRenderRD : public RendererCanvasRender { PipelineVariants pipeline_variants; String path; - Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; + HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<uint32_t> ubo_offsets; uint32_t ubo_size = 0; String code; - Map<StringName, Map<int, RID>> default_texture_params; + HashMap<StringName, HashMap<int, RID>> default_texture_params; bool uses_screen_texture = false; bool uses_sdf = false; @@ -205,7 +203,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { virtual void set_render_priority(int p_priority) {} virtual void set_next_pass(RID p_pass) {} - virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); + virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); virtual ~CanvasMaterialData(); }; @@ -462,7 +460,7 @@ public: void set_time(double p_time); void update(); bool free(RID p_rid); - RendererCanvasRenderRD(RendererStorageRD *p_storage); + RendererCanvasRenderRD(); ~RendererCanvasRenderRD(); }; diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp index 759b8690eb..a61172c8f5 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp @@ -154,12 +154,14 @@ uint64_t RendererCompositorRD::frame = 1; void RendererCompositorRD::finalize() { memdelete(scene); memdelete(canvas); - memdelete(storage); + memdelete(effects); + memdelete(fog); memdelete(particles_storage); memdelete(light_storage); memdelete(mesh_storage); memdelete(material_storage); memdelete(texture_storage); + memdelete(utilities); //only need to erase these, the rest are erased by cascade blit.shader.version_free(blit.shader_version); @@ -287,28 +289,29 @@ RendererCompositorRD::RendererCompositorRD() { singleton = this; + utilities = memnew(RendererRD::Utilities); texture_storage = memnew(RendererRD::TextureStorage); material_storage = memnew(RendererRD::MaterialStorage); mesh_storage = memnew(RendererRD::MeshStorage); light_storage = memnew(RendererRD::LightStorage); particles_storage = memnew(RendererRD::ParticlesStorage); - storage = memnew(RendererStorageRD); - canvas = memnew(RendererCanvasRenderRD(storage)); + fog = memnew(RendererRD::Fog); + canvas = memnew(RendererCanvasRenderRD()); back_end = (bool)(int)GLOBAL_GET("rendering/vulkan/rendering/back_end"); uint64_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE); if (back_end || textures_per_stage < 48) { - scene = memnew(RendererSceneRenderImplementation::RenderForwardMobile(storage)); + scene = memnew(RendererSceneRenderImplementation::RenderForwardMobile()); } else { // back_end == false // default to our high end renderer - scene = memnew(RendererSceneRenderImplementation::RenderForwardClustered(storage)); + scene = memnew(RendererSceneRenderImplementation::RenderForwardClustered()); } scene->init(); // now we're ready to create our effects, - storage->init_effects(!scene->_render_buffers_can_be_storage()); + effects = memnew(EffectsRD(!scene->_render_buffers_can_be_storage())); } RendererCompositorRD::~RendererCompositorRD() { diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h index 1fd6550fb8..2be55743fb 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.h +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h @@ -34,28 +34,32 @@ #include "core/os/os.h" #include "core/templates/thread_work_pool.h" #include "servers/rendering/renderer_compositor.h" +#include "servers/rendering/renderer_rd/effects_rd.h" +#include "servers/rendering/renderer_rd/environment/fog.h" #include "servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h" #include "servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h" #include "servers/rendering/renderer_rd/renderer_canvas_render_rd.h" -#include "servers/rendering/renderer_rd/renderer_storage_rd.h" #include "servers/rendering/renderer_rd/shaders/blit.glsl.gen.h" #include "servers/rendering/renderer_rd/storage_rd/light_storage.h" #include "servers/rendering/renderer_rd/storage_rd/material_storage.h" #include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h" #include "servers/rendering/renderer_rd/storage_rd/particles_storage.h" #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/utilities.h" #include "servers/rendering/renderer_rd/uniform_set_cache_rd.h" class RendererCompositorRD : public RendererCompositor { protected: UniformSetCacheRD *uniform_set_cache = nullptr; RendererCanvasRenderRD *canvas = nullptr; + RendererRD::Utilities *utilities = nullptr; RendererRD::LightStorage *light_storage = nullptr; RendererRD::MaterialStorage *material_storage = nullptr; RendererRD::MeshStorage *mesh_storage = nullptr; RendererRD::ParticlesStorage *particles_storage = nullptr; RendererRD::TextureStorage *texture_storage = nullptr; - RendererStorageRD *storage = nullptr; + RendererRD::Fog *fog = nullptr; + EffectsRD *effects = nullptr; RendererSceneRenderRD *scene = nullptr; enum BlitMode { @@ -90,7 +94,7 @@ protected: RID sampler; } blit; - Map<RID, RID> render_target_descriptors; + HashMap<RID, RID> render_target_descriptors; double time = 0.0; double delta = 0.0; @@ -98,12 +102,18 @@ protected: static uint64_t frame; public: - RendererLightStorage *get_light_storage() { return light_storage; }; - RendererMaterialStorage *get_material_storage() { return material_storage; }; - RendererMeshStorage *get_mesh_storage() { return mesh_storage; }; - RendererParticlesStorage *get_particles_storage() { return particles_storage; }; - RendererTextureStorage *get_texture_storage() { return texture_storage; }; - RendererStorage *get_storage() { return storage; } + RendererUtilities *get_utilities() { return utilities; }; + RendererLightStorage *get_light_storage() { return light_storage; } + RendererMaterialStorage *get_material_storage() { return material_storage; } + RendererMeshStorage *get_mesh_storage() { return mesh_storage; } + RendererParticlesStorage *get_particles_storage() { return particles_storage; } + RendererTextureStorage *get_texture_storage() { return texture_storage; } + RendererGI *get_gi() { + ERR_FAIL_NULL_V(scene, nullptr); + return scene->get_gi(); + } + RendererFog *get_fog() { return fog; } + EffectsRD *get_effects() { return effects; } RendererCanvasRender *get_canvas() { return canvas; } RendererSceneRender *get_scene() { return scene; } diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 21b1b45802..a2a0538e04 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -33,6 +33,7 @@ #include "core/config/project_settings.h" #include "core/os/os.h" #include "renderer_compositor_rd.h" +#include "servers/rendering/renderer_rd/environment/fog.h" #include "servers/rendering/renderer_rd/storage_rd/material_storage.h" #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/rendering_server_default.h" @@ -74,7 +75,7 @@ void RendererSceneRenderRD::sdfgi_update(RID p_render_buffers, RID p_environment rb->sdfgi = nullptr; } - RendererSceneGIRD::SDFGI *sdfgi = rb->sdfgi; + RendererRD::GI::SDFGI *sdfgi = rb->sdfgi; if (sdfgi == nullptr) { // re-create rb->sdfgi = gi.create_sdfgi(env, p_world_position, requested_history_size); @@ -95,9 +96,9 @@ int RendererSceneRenderRD::sdfgi_get_pending_region_count(RID p_render_buffers) int dirty_count = 0; for (uint32_t i = 0; i < rb->sdfgi->cascades.size(); i++) { - const RendererSceneGIRD::SDFGI::Cascade &c = rb->sdfgi->cascades[i]; + const RendererRD::GI::SDFGI::Cascade &c = rb->sdfgi->cascades[i]; - if (c.dirty_regions == RendererSceneGIRD::SDFGI::Cascade::DIRTY_ALL) { + if (c.dirty_regions == RendererRD::GI::SDFGI::Cascade::DIRTY_ALL) { dirty_count++; } else { for (int j = 0; j < 3; j++) { @@ -534,7 +535,7 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba return panorama; } else { const float bg_energy = env->bg_energy; - Color panorama_color = ((environment_background == RS::ENV_BG_CLEAR_COLOR) ? storage->get_default_clear_color() : env->bg_color); + Color panorama_color = ((environment_background == RS::ENV_BG_CLEAR_COLOR) ? RSG::texture_storage->get_default_clear_color() : env->bg_color); panorama_color = panorama_color.srgb_to_linear(); panorama_color.r *= bg_energy; panorama_color.g *= bg_energy; @@ -759,7 +760,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instanc } atlas->reflections.resize(atlas->count); for (int i = 0; i < atlas->count; i++) { - atlas->reflections.write[i].data.update_reflection_data(storage, atlas->size, mipmaps, false, atlas->reflection, i * 6, RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS, sky.roughness_layers, _render_buffers_get_color_format()); + atlas->reflections.write[i].data.update_reflection_data(atlas->size, mipmaps, false, atlas->reflection, i * 6, RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS, sky.roughness_layers, _render_buffers_get_color_format()); for (int j = 0; j < 6; j++) { atlas->reflections.write[i].fbs[j] = reflection_probe_create_framebuffer(atlas->reflections.write[i].data.layers[0].mipmaps[0].views[j], atlas->depth_buffer); } @@ -829,7 +830,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_postprocess_step(RID p_ins if (RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS) { // Using real time reflections, all roughness is done in one step - atlas->reflections.write[rpi->atlas_index].data.create_reflection_fast_filter(storage, false); + atlas->reflections.write[rpi->atlas_index].data.create_reflection_fast_filter(false); rpi->rendering = false; rpi->processing_side = 0; rpi->processing_layer = 1; @@ -837,7 +838,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_postprocess_step(RID p_ins } if (rpi->processing_layer > 1) { - atlas->reflections.write[rpi->atlas_index].data.create_reflection_importance_sample(storage, false, 10, rpi->processing_layer, sky.sky_ggx_samples_quality); + atlas->reflections.write[rpi->atlas_index].data.create_reflection_importance_sample(false, 10, rpi->processing_layer, sky.sky_ggx_samples_quality); rpi->processing_layer++; if (rpi->processing_layer == atlas->reflections[rpi->atlas_index].data.layers[0].mipmaps.size()) { rpi->rendering = false; @@ -848,7 +849,7 @@ bool RendererSceneRenderRD::reflection_probe_instance_postprocess_step(RID p_ins return false; } else { - atlas->reflections.write[rpi->atlas_index].data.create_reflection_importance_sample(storage, false, rpi->processing_side, rpi->processing_layer, sky.sky_ggx_samples_quality); + atlas->reflections.write[rpi->atlas_index].data.create_reflection_importance_sample(false, rpi->processing_side, rpi->processing_layer, sky.sky_ggx_samples_quality); } rpi->processing_side++; @@ -1533,7 +1534,7 @@ void RendererSceneRenderRD::voxel_gi_update(RID p_probe, bool p_update_light_ins gi.voxel_gi_update(p_probe, p_update_light_instances, p_light_instances, p_dynamic_objects, this); } -void RendererSceneRenderRD::_debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform) { +void RendererSceneRenderRD::_debug_sdfgi_probes(RID p_render_buffers, RID p_framebuffer, const uint32_t p_view_count, const CameraMatrix *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) { RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND(!rb); @@ -1541,7 +1542,7 @@ void RendererSceneRenderRD::_debug_sdfgi_probes(RID p_render_buffers, RD::DrawLi return; //nothing to debug } - rb->sdfgi->debug_probes(p_draw_list, p_framebuffer, p_camera_with_transform); + rb->sdfgi->debug_probes(p_framebuffer, p_view_count, p_camera_with_transforms, p_will_continue_color, p_will_continue_depth); } //////////////////////////////// @@ -1826,6 +1827,16 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) { rb->sss_texture = RID(); } + if (rb->vrs_fb.is_valid()) { + RD::get_singleton()->free(rb->vrs_fb); + rb->vrs_fb = RID(); + } + + if (rb->vrs_texture.is_valid()) { + RD::get_singleton()->free(rb->vrs_texture); + rb->vrs_texture = RID(); + } + for (int i = 0; i < 2; i++) { for (int l = 0; l < rb->blur[i].layers.size(); l++) { for (int m = 0; m < rb->blur[i].layers[l].mipmaps.size(); m++) { @@ -1935,17 +1946,22 @@ void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) { rb->ssr.normal_scaled = RID(); } - if (rb->ambient_buffer.is_valid()) { - RD::get_singleton()->free(rb->ambient_buffer); - RD::get_singleton()->free(rb->reflection_buffer); - rb->ambient_buffer = RID(); - rb->reflection_buffer = RID(); + if (rb->taa.history.is_valid()) { + RD::get_singleton()->free(rb->taa.history); + rb->taa.history = RID(); } - if (rb->gi.voxel_gi_buffer.is_valid()) { - RD::get_singleton()->free(rb->gi.voxel_gi_buffer); - rb->gi.voxel_gi_buffer = RID(); + if (rb->taa.temp.is_valid()) { + RD::get_singleton()->free(rb->taa.temp); + rb->taa.temp = RID(); } + + if (rb->taa.prev_velocity.is_valid()) { + RD::get_singleton()->free(rb->taa.prev_velocity); + rb->taa.prev_velocity = RID(); + } + + rb->rbgi.free(); } void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatrix &p_camera) { @@ -1963,7 +1979,7 @@ void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatri _allocate_blur_textures(rb); } - storage->get_effects()->sub_surface_scattering(rb->internal_texture, rb->sss_texture, rb->depth_texture, p_camera, Size2i(rb->internal_width, rb->internal_height), sss_scale, sss_depth_scale, sss_quality); + RendererCompositorRD::singleton->get_effects()->sub_surface_scattering(rb->internal_texture, rb->sss_texture, rb->depth_texture, p_camera, Size2i(rb->internal_width, rb->internal_height), sss_scale, sss_depth_scale, sss_quality); } void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive) { @@ -1974,7 +1990,7 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb if (!can_use_effects) { //just copy - storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, RID()); + RendererCompositorRD::singleton->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, RID()); return; } @@ -2014,8 +2030,8 @@ void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_frameb _allocate_blur_textures(rb); } - storage->get_effects()->screen_space_reflection(rb->internal_texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].layers[0].mipmaps[1].texture, rb->blur[1].layers[0].mipmaps[0].texture, Size2i(rb->internal_width / 2, rb->internal_height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection); - storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, rb->blur[0].layers[0].mipmaps[1].texture); + RendererCompositorRD::singleton->get_effects()->screen_space_reflection(rb->internal_texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].layers[0].mipmaps[1].texture, rb->blur[1].layers[0].mipmaps[0].texture, Size2i(rb->internal_width / 2, rb->internal_height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection); + RendererCompositorRD::singleton->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, rb->blur[0].layers[0].mipmaps[1].texture); } void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection) { @@ -2140,7 +2156,7 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen settings.half_screen_size = Size2i(buffer_width, buffer_height); settings.quarter_screen_size = Size2i(half_width, half_height); - storage->get_effects()->generate_ssao(p_normal_buffer, rb->ss_effects.ssao.depth_texture_view, rb->ss_effects.ssao.ao_deinterleaved, rb->ss_effects.ssao.ao_deinterleaved_slices, rb->ss_effects.ssao.ao_pong, rb->ss_effects.ssao.ao_pong_slices, rb->ss_effects.ssao.ao_final, rb->ss_effects.ssao.importance_map[0], rb->ss_effects.ssao.importance_map[1], p_projection, settings, uniform_sets_are_invalid, rb->ss_effects.ssao.gather_uniform_set, rb->ss_effects.ssao.importance_map_uniform_set); + RendererCompositorRD::singleton->get_effects()->generate_ssao(p_normal_buffer, rb->ss_effects.ssao.depth_texture_view, rb->ss_effects.ssao.ao_deinterleaved, rb->ss_effects.ssao.ao_deinterleaved_slices, rb->ss_effects.ssao.ao_pong, rb->ss_effects.ssao.ao_pong_slices, rb->ss_effects.ssao.ao_final, rb->ss_effects.ssao.importance_map[0], rb->ss_effects.ssao.importance_map[1], p_projection, settings, uniform_sets_are_invalid, rb->ss_effects.ssao.gather_uniform_set, rb->ss_effects.ssao.importance_map_uniform_set); } void RendererSceneRenderRD::_process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection, const Transform3D &p_transform) { @@ -2301,7 +2317,7 @@ void RendererSceneRenderRD::_process_ssil(RID p_render_buffers, RID p_environmen transform.set_origin(Vector3(0.0, 0.0, 0.0)); CameraMatrix last_frame_projection = rb->ss_effects.last_frame_projection * CameraMatrix(rb->ss_effects.last_frame_transform.affine_inverse()) * CameraMatrix(transform) * projection.inverse(); - storage->get_effects()->screen_space_indirect_lighting(rb->ss_effects.last_frame, rb->ss_effects.ssil.ssil_final, p_normal_buffer, rb->ss_effects.ssil.depth_texture_view, rb->ss_effects.ssil.deinterleaved, rb->ss_effects.ssil.deinterleaved_slices, rb->ss_effects.ssil.pong, rb->ss_effects.ssil.pong_slices, rb->ss_effects.ssil.importance_map[0], rb->ss_effects.ssil.importance_map[1], rb->ss_effects.ssil.edges, rb->ss_effects.ssil.edges_slices, p_projection, last_frame_projection, settings, uniform_sets_are_invalid, rb->ss_effects.ssil.gather_uniform_set, rb->ss_effects.ssil.importance_map_uniform_set, rb->ss_effects.ssil.projection_uniform_set); + RendererCompositorRD::singleton->get_effects()->screen_space_indirect_lighting(rb->ss_effects.last_frame, rb->ss_effects.ssil.ssil_final, p_normal_buffer, rb->ss_effects.ssil.depth_texture_view, rb->ss_effects.ssil.deinterleaved, rb->ss_effects.ssil.deinterleaved_slices, rb->ss_effects.ssil.pong, rb->ss_effects.ssil.pong_slices, rb->ss_effects.ssil.importance_map[0], rb->ss_effects.ssil.importance_map[1], rb->ss_effects.ssil.edges, rb->ss_effects.ssil.edges_slices, p_projection, last_frame_projection, settings, uniform_sets_are_invalid, rb->ss_effects.ssil.gather_uniform_set, rb->ss_effects.ssil.importance_map_uniform_set, rb->ss_effects.ssil.projection_uniform_set); rb->ss_effects.last_frame_projection = projection; rb->ss_effects.last_frame_transform = transform; } @@ -2323,6 +2339,41 @@ void RendererSceneRenderRD::_copy_framebuffer_to_ssil(RID p_render_buffers) { } } +void RendererSceneRenderRD::_process_taa(RID p_render_buffers, RID p_velocity_buffer, float p_z_near, float p_z_far) { + RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); + ERR_FAIL_COND(!rb); + + bool just_allocated = false; + if (rb->taa.history.is_null()) { + RD::TextureFormat tf; + if (rb->view_count > 1) { + tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + } + tf.format = _render_buffers_get_color_format(); + tf.width = rb->internal_width; + tf.height = rb->internal_height; + tf.array_layers = rb->view_count; // create a layer for every view + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | (_render_buffers_can_be_storage() ? RD::TEXTURE_USAGE_STORAGE_BIT : 0); + + rb->taa.history = RD::get_singleton()->texture_create(tf, RD::TextureView()); + rb->taa.temp = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + tf.format = RD::DATA_FORMAT_R16G16_SFLOAT; + rb->taa.prev_velocity = RD::get_singleton()->texture_create(tf, RD::TextureView()); + just_allocated = true; + } + + RD::get_singleton()->draw_command_begin_label("TAA"); + if (!just_allocated) { + RendererCompositorRD::singleton->get_effects()->taa_resolve(rb->internal_texture, rb->taa.temp, rb->depth_texture, p_velocity_buffer, rb->taa.prev_velocity, rb->taa.history, Size2(rb->internal_width, rb->internal_height), p_z_near, p_z_far); + copy_effects->copy_to_rect(rb->taa.temp, rb->internal_texture, Rect2(0, 0, rb->internal_width, rb->internal_height)); + } + + copy_effects->copy_to_rect(rb->internal_texture, rb->taa.history, Rect2(0, 0, rb->internal_width, rb->internal_height)); + copy_effects->copy_to_rect(p_velocity_buffer, rb->taa.prev_velocity, Rect2(0, 0, rb->width, rb->height)); + RD::get_singleton()->draw_command_end_label(); +} + void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderDataRD *p_render_data) { RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers); ERR_FAIL_COND(!rb); @@ -2388,6 +2439,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende bool can_use_storage = _render_buffers_can_be_storage(); if (can_use_effects && camfx && (camfx->dof_blur_near_enabled || camfx->dof_blur_far_enabled) && camfx->dof_blur_amount > 0.0) { + RENDER_TIMESTAMP("Depth of Field"); RD::get_singleton()->draw_command_begin_label("DOF"); if (rb->blur[0].texture.is_null()) { _allocate_blur_textures(rb); @@ -2440,6 +2492,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende } if (can_use_effects && env && env->auto_exposure) { + RENDER_TIMESTAMP("Auto exposure"); RD::get_singleton()->draw_command_begin_label("Auto exposure"); if (rb->luminance.current.is_null()) { _allocate_luminance_textures(rb); @@ -2450,9 +2503,9 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende double step = env->auto_exp_speed * time_step; if (can_use_storage) { - storage->get_effects()->luminance_reduction(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate); + RendererCompositorRD::singleton->get_effects()->luminance_reduction(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate); } else { - storage->get_effects()->luminance_reduction_raster(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate); + RendererCompositorRD::singleton->get_effects()->luminance_reduction_raster(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate); } // Swap final reduce with prev luminance. SWAP(rb->luminance.current, rb->luminance.reduce.write[rb->luminance.reduce.size() - 1]); @@ -2467,6 +2520,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende int max_glow_level = -1; if (can_use_effects && env && env->glow_enabled) { + RENDER_TIMESTAMP("Glow"); RD::get_singleton()->draw_command_begin_label("Gaussian Glow"); /* see that blur textures are allocated */ @@ -2515,6 +2569,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende } { + RENDER_TIMESTAMP("Tonemap"); RD::get_singleton()->draw_command_begin_label("Tonemap"); RendererRD::ToneMapper::TonemapSettings tonemap; @@ -2595,7 +2650,7 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende if (can_use_effects && can_use_storage && (rb->internal_width != rb->width || rb->internal_height != rb->height)) { RD::get_singleton()->draw_command_begin_label("FSR 1.0 Upscale"); - storage->get_effects()->fsr_upscale(rb->internal_texture, rb->upscale_texture, rb->texture, Size2i(rb->internal_width, rb->internal_height), Size2i(rb->width, rb->height), rb->fsr_sharpness); + RendererCompositorRD::singleton->get_effects()->fsr_upscale(rb->internal_texture, rb->upscale_texture, rb->texture, Size2i(rb->internal_width, rb->internal_height), Size2i(rb->width, rb->height), rb->fsr_sharpness); RD::get_singleton()->draw_command_end_label(); } @@ -2742,11 +2797,11 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID copy_effects->copy_to_fb_rect(_render_buffers_get_normal_texture(p_render_buffers), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false); } - if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_GI_BUFFER && rb->ambient_buffer.is_valid()) { + if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_GI_BUFFER && rb->rbgi.ambient_buffer.is_valid()) { Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); - RID ambient_texture = rb->ambient_buffer; - RID reflection_texture = rb->reflection_buffer; - copy_effects->copy_to_fb_rect(ambient_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false, false, true, reflection_texture); + RID ambient_texture = rb->rbgi.ambient_buffer; + RID reflection_texture = rb->rbgi.reflection_buffer; + copy_effects->copy_to_fb_rect(ambient_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false, false, true, reflection_texture, rb->view_count > 1); } if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_OCCLUDERS) { @@ -2755,6 +2810,11 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID copy_effects->copy_to_fb_rect(texture_storage->texture_get_rd_texture(p_occlusion_buffer), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize), true, false); } } + + if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS && _render_buffers_get_velocity_texture(p_render_buffers).is_valid()) { + Size2 rtsize = texture_storage->render_target_get_size(rb->render_target); + copy_effects->copy_to_fb_rect(_render_buffers_get_velocity_texture(p_render_buffers), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false); + } } void RendererSceneRenderRD::environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) { @@ -2810,10 +2870,10 @@ RID RendererSceneRenderRD::render_buffers_get_ssil_texture(RID p_render_buffers) RID RendererSceneRenderRD::render_buffers_get_voxel_gi_buffer(RID p_render_buffers) { RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND_V(!rb, RID()); - if (rb->gi.voxel_gi_buffer.is_null()) { - rb->gi.voxel_gi_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(RendererSceneGIRD::VoxelGIData) * RendererSceneGIRD::MAX_VOXEL_GI_INSTANCES); + if (rb->rbgi.voxel_gi_buffer.is_null()) { + rb->rbgi.voxel_gi_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(RendererRD::GI::VoxelGIData) * RendererRD::GI::MAX_VOXEL_GI_INSTANCES); } - return rb->gi.voxel_gi_buffer; + return rb->rbgi.voxel_gi_buffer; } RID RendererSceneRenderRD::render_buffers_get_default_voxel_gi_buffer() { @@ -2823,12 +2883,13 @@ RID RendererSceneRenderRD::render_buffers_get_default_voxel_gi_buffer() { RID RendererSceneRenderRD::render_buffers_get_gi_ambient_texture(RID p_render_buffers) { RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND_V(!rb, RID()); - return rb->ambient_buffer; + + return rb->rbgi.ambient_buffer; } RID RendererSceneRenderRD::render_buffers_get_gi_reflection_texture(RID p_render_buffers) { RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers); ERR_FAIL_COND_V(!rb, RID()); - return rb->reflection_buffer; + return rb->rbgi.reflection_buffer; } uint32_t RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_count(RID p_render_buffers) const { @@ -2866,7 +2927,7 @@ Vector3i RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_probe_offset(RI ERR_FAIL_COND_V(!rb, Vector3i()); ERR_FAIL_COND_V(!rb->sdfgi, Vector3i()); ERR_FAIL_UNSIGNED_INDEX_V(p_cascade, rb->sdfgi->cascades.size(), Vector3i()); - int32_t probe_divisor = rb->sdfgi->cascade_size / RendererSceneGIRD::SDFGI::PROBE_DIVISOR; + int32_t probe_divisor = rb->sdfgi->cascade_size / RendererRD::GI::SDFGI::PROBE_DIVISOR; return rb->sdfgi->cascades[p_cascade].position / probe_divisor; } @@ -2972,7 +3033,7 @@ bool RendererSceneRenderRD::_render_buffers_can_be_storage() { return true; } -void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) { +void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); @@ -3000,6 +3061,7 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p rb->render_target = p_render_target; rb->msaa = p_msaa; rb->screen_space_aa = p_screen_space_aa; + rb->use_taa = p_use_taa; rb->use_debanding = p_use_debanding; rb->view_count = p_view_count; @@ -3046,7 +3108,7 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; } if (rb->msaa == RS::VIEWPORT_MSAA_DISABLED) { - tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT; + tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, (RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT)) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT; } else { tf.format = RD::DATA_FORMAT_R32_SFLOAT; } @@ -3078,14 +3140,14 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p if (rb->view_count == 1) { // copy as a convenience RenderBuffers::View view; - view.view_texture = rb->internal_texture; + view.view_texture = rb->texture; view.view_depth = rb->depth_texture; view.view_fb = rb->texture_fb; rb->views.push_back(view); } else { for (uint32_t i = 0; i < rb->view_count; i++) { RenderBuffers::View view; - view.view_texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->internal_texture, i, 0); + view.view_texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->texture, i, 0); view.view_depth = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->depth_texture, i, 0); if (!_render_buffers_can_be_storage()) { @@ -3099,8 +3161,13 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p } } + RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(rb->render_target); + if (is_vrs_supported() && vrs_mode != RS::VIEWPORT_VRS_DISABLED) { + vrs->create_vrs_texture(p_internal_width, p_internal_height, p_view_count, rb->vrs_texture, rb->vrs_fb); + } + RID target_texture = texture_storage->render_target_get_rd_texture(rb->render_target); - rb->data->configure(rb->internal_texture, rb->depth_texture, target_texture, p_internal_width, p_internal_height, p_msaa, p_view_count); + rb->data->configure(rb->internal_texture, rb->depth_texture, target_texture, p_internal_width, p_internal_height, p_msaa, p_use_taa, p_view_count, rb->vrs_texture); if (is_clustered_enabled()) { rb->cluster_builder->setup(Size2i(p_internal_width, p_internal_height), max_cluster_elements, rb->depth_texture, RendererRD::MaterialStorage::get_singleton()->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->internal_texture); @@ -3124,7 +3191,7 @@ void RendererSceneRenderRD::sub_surface_scattering_set_scale(float p_scale, floa sss_depth_scale = p_depth_scale; } -void RendererSceneRenderRD::shadows_quality_set(RS::ShadowQuality p_quality) { +void RendererSceneRenderRD::positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) { ERR_FAIL_INDEX_MSG(p_quality, RS::SHADOW_QUALITY_MAX, "Shadow quality too high, please see RenderingServer's ShadowQuality enum"); if (shadows_quality != p_quality) { @@ -3171,7 +3238,7 @@ void RendererSceneRenderRD::shadows_quality_set(RS::ShadowQuality p_quality) { _update_shader_quality_settings(); } -void RendererSceneRenderRD::directional_shadow_quality_set(RS::ShadowQuality p_quality) { +void RendererSceneRenderRD::directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) { ERR_FAIL_INDEX_MSG(p_quality, RS::SHADOW_QUALITY_MAX, "Shadow quality too high, please see RenderingServer's ShadowQuality enum"); if (directional_shadow_quality != p_quality) { @@ -3313,7 +3380,7 @@ void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflecti Transform3D transform = rpi->transform; Transform3D proj = (p_camera_inverse_transform * transform).inverse(); - RendererStorageRD::store_transform(proj, reflection_ubo.local_matrix); + RendererRD::MaterialStorage::store_transform(proj, reflection_ubo.local_matrix); if (current_cluster_builder != nullptr) { current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_REFLECTION_PROBE, transform, extents); @@ -3397,7 +3464,9 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const // technically this will keep expanding until reaching the sun, but all we care // is expand until we reach the radius of the near plane (there can't be more occluders than that) angular_diameter = Math::tan(Math::deg2rad(angular_diameter)); - if (light_storage->light_has_shadow(base)) { + if (light_storage->light_has_shadow(base) && light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR) > 0.0) { + // Only enable PCSS-like soft shadows if blurring is enabled. + // Otherwise, performance would decrease with no visual difference. r_directional_light_soft_shadows = true; } } else { @@ -3429,7 +3498,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const light_data.shadow_transmittance_bias[j] = light_storage->light_get_transmittance_bias(base) * bias_scale; light_data.shadow_z_range[j] = li->shadow_transform[j].farplane; light_data.shadow_range_begin[j] = li->shadow_transform[j].range_begin; - RendererStorageRD::store_camera(shadow_mtx, light_data.shadow_matrices[j]); + RendererRD::MaterialStorage::store_camera(shadow_mtx, light_data.shadow_matrices[j]); Vector2 uv_scale = li->shadow_transform[j].uv_scale; uv_scale *= atlas_rect.size; //adapt to atlas size @@ -3674,9 +3743,11 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const if (type == RS::LIGHT_OMNI) { Transform3D proj = (inverse_transform * light_transform).inverse(); - RendererStorageRD::store_transform(proj, light_data.shadow_matrix); + RendererRD::MaterialStorage::store_transform(proj, light_data.shadow_matrix); - if (size > 0.0) { + if (size > 0.0 && light_data.soft_shadow_scale > 0.0) { + // Only enable PCSS-like soft shadows if blurring is enabled. + // Otherwise, performance would decrease with no visual difference. light_data.soft_shadow_size = size; } else { light_data.soft_shadow_size = 0.0; @@ -3691,9 +3762,11 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const bias.set_light_bias(); CameraMatrix shadow_mtx = bias * li->shadow_transform[0].camera * modelview; - RendererStorageRD::store_camera(shadow_mtx, light_data.shadow_matrix); + RendererRD::MaterialStorage::store_camera(shadow_mtx, light_data.shadow_matrix); - if (size > 0.0) { + if (size > 0.0 && light_data.soft_shadow_scale > 0.0) { + // Only enable PCSS-like soft shadows if blurring is enabled. + // Otherwise, performance would decrease with no visual difference. CameraMatrix cm = li->shadow_transform[0].camera; float half_np = cm.get_z_near() * Math::tan(Math::deg2rad(spot_angle)); light_data.soft_shadow_size = (size * 0.5 / radius) / (half_np / cm.get_z_near()) * rect.size.width; @@ -3808,7 +3881,7 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const Transform3D scale_xform; scale_xform.basis.scale(decal_extents); Transform3D to_decal_xform = (p_camera_inverse_xform * di->transform * scale_xform * uv_xform).affine_inverse(); - RendererStorageRD::store_transform(to_decal_xform, dd.xform); + RendererRD::MaterialStorage::store_transform(to_decal_xform, dd.xform); Vector3 normal = xform.basis.get_column(Vector3::AXIS_Y).normalized(); normal = p_camera_inverse_xform.basis.xform(normal); //camera is normalized, so fine @@ -3846,7 +3919,7 @@ void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const dd.normal_rect[3] = rect.size.y; Basis normal_xform = p_camera_inverse_xform.basis * xform.basis.orthonormalized(); - RendererStorageRD::store_basis_3x4(normal_xform, dd.normal_xform); + RendererRD::MaterialStorage::store_basis_3x4(normal_xform, dd.normal_xform); } else { dd.normal_rect[0] = 0; dd.normal_rect[1] = 0; @@ -3959,45 +4032,45 @@ void RendererSceneRenderRD::FogShaderData::set_default_texture_param(const Strin } } else { if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = Map<int, RID>(); + default_texture_params[p_name] = HashMap<int, RID>(); } default_texture_params[p_name][p_index] = p_texture; } } void RendererSceneRenderRD::FogShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { - Map<int, StringName> order; + RBMap<int, StringName> order; - for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) { - if (E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E->get().scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { + for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { + if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { continue; } - if (E->get().texture_order >= 0) { - order[E->get().texture_order + 100000] = E->key(); + if (E.value.texture_order >= 0) { + order[E.value.texture_order + 100000] = E.key; } else { - order[E->get().order] = E->key(); + order[E.value.order] = E.key; } } - for (Map<int, StringName>::Element *E = order.front(); E; E = E->next()) { - PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E->get()]); - pi.name = E->get(); + for (const KeyValue<int, StringName> &E : order) { + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]); + pi.name = E.value; p_param_list->push_back(pi); } } void RendererSceneRenderRD::FogShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const { - for (Map<StringName, ShaderLanguage::ShaderNode::Uniform>::Element *E = uniforms.front(); E; E = E->next()) { - if (E->get().scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { + for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { + if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { continue; } RendererMaterialStorage::InstanceShaderParam p; - p.info = ShaderLanguage::uniform_to_property_info(E->get()); - p.info.name = E->key(); //supply name - p.index = E->get().instance_index; - p.default_value = ShaderLanguage::constant_value_to_variant(E->get().default_value, E->get().type, E->get().array_size, E->get().hint); + p.info = ShaderLanguage::uniform_to_property_info(E.value); + p.info.name = E.key; //supply name + p.index = E.value.instance_index; + p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint); p_param_list->push_back(p); } } @@ -4045,7 +4118,7 @@ RendererSceneRenderRD::FogShaderData::~FogShaderData() { //////////////////////////////////////////////////////////////////////////////// // Fog material -bool RendererSceneRenderRD::FogMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +bool RendererSceneRenderRD::FogMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); uniform_set_updated = true; @@ -4093,6 +4166,9 @@ void RendererSceneRenderRD::_volumetric_fog_erase(RenderBuffers *rb) { if (rb->volumetric_fog->fog_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->fog_uniform_set)) { RD::get_singleton()->free(rb->volumetric_fog->fog_uniform_set); } + if (rb->volumetric_fog->process_uniform_set_density.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set_density)) { + RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set_density); + } if (rb->volumetric_fog->process_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set)) { RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set); } @@ -4130,7 +4206,7 @@ Vector3i RendererSceneRenderRD::_point_get_position_in_froxel_volume(const Vecto return Vector3i(fog_position); } -void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) { +void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); @@ -4265,9 +4341,9 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e params.detail_spread = env->volumetric_fog_detail_spread; params.temporal_blend = env->volumetric_fog_temporal_reprojection_amount; - Transform3D to_prev_cam_view = rb->volumetric_fog->prev_cam_transform.affine_inverse() * p_cam_transform; - storage->store_transform(to_prev_cam_view, params.to_prev_view); - storage->store_transform(p_cam_transform, params.transform); + Transform3D to_prev_cam_view = p_prev_cam_inv_transform * p_cam_transform; + RendererRD::MaterialStorage::store_transform(to_prev_cam_view, params.to_prev_view); + RendererRD::MaterialStorage::store_transform(p_cam_transform, params.transform); RD::get_singleton()->buffer_update(volumetric_fog.volume_ubo, 0, sizeof(VolumetricFogShader::VolumeUBO), ¶ms, RD::BARRIER_MASK_COMPUTE); @@ -4329,7 +4405,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e ERR_FAIL_COND(!fog_volume_instance); RID fog_volume = fog_volume_instance->volume; - RID fog_material = storage->fog_volume_get_material(fog_volume); + RID fog_material = RendererRD::Fog::get_singleton()->fog_volume_get_material(fog_volume); FogMaterialData *material = nullptr; @@ -4358,10 +4434,11 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e Vector3i kernel_size = Vector3i(); Vector3 position = fog_volume_instance->transform.get_origin(); - RS::FogVolumeShape volume_type = storage->fog_volume_get_shape(fog_volume); - Vector3 extents = storage->fog_volume_get_extents(fog_volume); + RS::FogVolumeShape volume_type = RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume); + Vector3 extents = RendererRD::Fog::get_singleton()->fog_volume_get_extents(fog_volume); - if (volume_type == RS::FOG_VOLUME_SHAPE_BOX || volume_type == RS::FOG_VOLUME_SHAPE_ELLIPSOID) { + if (volume_type != RS::FOG_VOLUME_SHAPE_WORLD) { + // Local fog volume. Vector3i points[8]; points[0] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform); points[1] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform); @@ -4401,8 +4478,8 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e volumetric_fog.push_constant.corner[0] = min.x; volumetric_fog.push_constant.corner[1] = min.y; volumetric_fog.push_constant.corner[2] = min.z; - volumetric_fog.push_constant.shape = uint32_t(storage->fog_volume_get_shape(fog_volume)); - storage->store_transform(fog_volume_instance->transform.affine_inverse(), volumetric_fog.push_constant.transform); + volumetric_fog.push_constant.shape = uint32_t(RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume)); + RendererRD::MaterialStorage::store_transform(fog_volume_instance->transform.affine_inverse(), volumetric_fog.push_constant.transform); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shader_data->pipeline); @@ -4424,7 +4501,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e RD::get_singleton()->compute_list_end(); } - if (rb->volumetric_fog->process_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set)) { + if (rb->volumetric_fog->process_uniform_set_density.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set_density)) { //re create uniform set if needed Vector<RD::Uniform> uniforms; Vector<RD::Uniform> copy_uniforms; @@ -4548,8 +4625,8 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e RD::Uniform u; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; u.binding = 12; - for (int i = 0; i < RendererSceneGIRD::MAX_VOXEL_GI_INSTANCES; i++) { - u.append_id(rb->gi.voxel_gi_textures[i]); + for (int i = 0; i < RendererRD::GI::MAX_VOXEL_GI_INSTANCES; i++) { + u.append_id(rb->rbgi.voxel_gi_textures[i]); } uniforms.push_back(u); copy_uniforms.push_back(u); @@ -4624,7 +4701,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e rb->volumetric_fog->copy_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0); - rb->volumetric_fog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0); + rb->volumetric_fog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0); RID aux7 = uniforms.write[7].get_id(0); RID aux8 = uniforms.write[8].get_id(0); @@ -4632,7 +4709,11 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e uniforms.write[7].set_id(0, aux8); uniforms.write[8].set_id(0, aux7); - rb->volumetric_fog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, 0), 0); + rb->volumetric_fog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0); + + uniforms.remove_at(8); + uniforms.write[7].set_id(0, aux7); + rb->volumetric_fog->process_uniform_set_density = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0); } bool using_sdfgi = env->volumetric_fog_gi_inject > 0.0001 && env->sdfgi_enabled && (rb->sdfgi != nullptr); @@ -4742,8 +4823,8 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e params.max_voxel_gi_instances = env->volumetric_fog_gi_inject > 0.001 ? p_voxel_gi_count : 0; params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES; - Transform3D to_prev_cam_view = rb->volumetric_fog->prev_cam_transform.affine_inverse() * p_cam_transform; - storage->store_transform(to_prev_cam_view, params.to_prev_view); + Transform3D to_prev_cam_view = p_prev_cam_inv_transform * p_cam_transform; + RendererRD::MaterialStorage::store_transform(to_prev_cam_view, params.to_prev_view); params.use_temporal_reprojection = env->volumetric_fog_temporal_reprojection; params.temporal_blend = env->volumetric_fog_temporal_reprojection_amount; @@ -4764,7 +4845,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e Basis sky_transform = env->sky_orientation; sky_transform = sky_transform.inverse() * p_cam_transform.basis; - RendererStorageRD::store_transform_3x3(sky_transform, params.radiance_inverse_xform); + RendererRD::MaterialStorage::store_transform_3x3(sky_transform, params.radiance_inverse_xform); RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog"); @@ -4775,7 +4856,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[using_sdfgi ? VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI : VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set, 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set_density, 0); if (using_sdfgi) { RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->sdfgi_uniform_set, 1); @@ -4828,8 +4909,6 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e RENDER_TIMESTAMP("< Volumetric Fog"); RD::get_singleton()->draw_command_end_label(); RD::get_singleton()->draw_command_end_label(); - - rb->volumetric_fog->prev_cam_transform = p_cam_transform; } bool RendererSceneRenderRD::_needs_post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi) { @@ -4865,7 +4944,7 @@ void RendererSceneRenderRD::_pre_resolve_render(RenderDataRD *p_render_data, boo } } -void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer) { +void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices) { // Render shadows while GI is rendering, due to how barriers are handled, this should happen at the same time RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); @@ -4940,7 +5019,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool //start GI if (render_gi) { - gi.process_gi(p_render_data->render_buffers, p_normal_roughness_buffer, p_voxel_gi_buffer, p_render_data->environment, p_render_data->cam_projection, p_render_data->cam_transform, *p_render_data->voxel_gi_instances, this); + gi.process_gi(p_render_data->render_buffers, p_normal_roughness_slices, p_voxel_gi_buffer, p_vrs_slices, p_render_data->environment, p_render_data->view_count, p_render_data->view_projection, p_render_data->view_eye_offset, p_render_data->cam_transform, *p_render_data->voxel_gi_instances, this); } //Do shadow rendering (in parallel with GI) @@ -4977,15 +5056,17 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool invalidate_uniform_set = true; } - storage->get_effects()->downsample_depth(rb->depth_texture, rb->ss_effects.linear_depth_slices, ssao_quality, ssil_quality, invalidate_uniform_set, ssao_half_size, ssil_half_size, Size2i(rb->width, rb->height), p_render_data->cam_projection); + RendererCompositorRD::singleton->get_effects()->downsample_depth(rb->depth_texture, rb->ss_effects.linear_depth_slices, ssao_quality, ssil_quality, invalidate_uniform_set, ssao_half_size, ssil_half_size, Size2i(rb->width, rb->height), p_render_data->cam_projection); } if (p_use_ssao) { - _process_ssao(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_buffer, p_render_data->cam_projection); + // TODO make these proper stereo + _process_ssao(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_slices[0], p_render_data->cam_projection); } if (p_use_ssil) { - _process_ssil(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_buffer, p_render_data->cam_projection, p_render_data->cam_transform); + // TODO make these proper stereo + _process_ssil(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_slices[0], p_render_data->cam_projection, p_render_data->cam_transform); } } @@ -5027,12 +5108,12 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool } } if (is_volumetric_supported()) { - _update_volumetric_fog(p_render_data->render_buffers, p_render_data->environment, p_render_data->cam_projection, p_render_data->cam_transform, p_render_data->shadow_atlas, directional_light_count, directional_shadows, positional_light_count, render_state.voxel_gi_count, *p_render_data->fog_volumes); + _update_volumetric_fog(p_render_data->render_buffers, p_render_data->environment, p_render_data->cam_projection, p_render_data->cam_transform, p_render_data->prev_cam_transform.affine_inverse(), p_render_data->shadow_atlas, directional_light_count, directional_shadows, positional_light_count, render_state.voxel_gi_count, *p_render_data->fog_volumes); } } } -void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) { +void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); // getting this here now so we can direct call a bunch of things more easily @@ -5050,14 +5131,23 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData // Our first camera is used by default render_data.cam_transform = p_camera_data->main_transform; render_data.cam_projection = p_camera_data->main_projection; - render_data.view_projection[0] = p_camera_data->main_projection; render_data.cam_orthogonal = p_camera_data->is_orthogonal; + render_data.taa_jitter = p_camera_data->taa_jitter; render_data.view_count = p_camera_data->view_count; for (uint32_t v = 0; v < p_camera_data->view_count; v++) { + render_data.view_eye_offset[v] = p_camera_data->view_offset[v].origin; render_data.view_projection[v] = p_camera_data->view_projection[v]; } + render_data.prev_cam_transform = p_prev_camera_data->main_transform; + render_data.prev_cam_projection = p_prev_camera_data->main_projection; + render_data.prev_taa_jitter = p_prev_camera_data->taa_jitter; + + for (uint32_t v = 0; v < p_camera_data->view_count; v++) { + render_data.prev_view_projection[v] = p_prev_camera_data->view_projection[v]; + } + render_data.z_near = p_camera_data->main_projection.get_z_near(); render_data.z_far = p_camera_data->main_projection.get_z_far(); @@ -5115,13 +5205,13 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData if (p_render_buffers.is_valid()) { clear_color = texture_storage->render_target_get_clear_request_color(rb->render_target); } else { - clear_color = storage->get_default_clear_color(); + clear_color = RSG::texture_storage->get_default_clear_color(); } //assign render indices to voxel_gi_instances if (is_dynamic_gi_supported()) { for (uint32_t i = 0; i < (uint32_t)p_voxel_gi_instances.size(); i++) { - RendererSceneGIRD::VoxelGIInstance *voxel_gi_inst = gi.voxel_gi_instance_owner.get_or_null(p_voxel_gi_instances[i]); + RendererRD::GI::VoxelGIInstance *voxel_gi_inst = gi.voxel_gi_instance_owner.get_or_null(p_voxel_gi_instances[i]); if (voxel_gi_inst) { voxel_gi_inst->render_index = i; } @@ -5165,18 +5255,28 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData render_data.cluster_max_elements = current_cluster_builder->get_max_cluster_elements(); } + if (rb != nullptr && rb->vrs_fb.is_valid()) { + // vrs_fb will only be valid if vrs is enabled + vrs->update_vrs_texture(rb->vrs_fb, rb->render_target); + } + _render_scene(&render_data, clear_color); if (p_render_buffers.is_valid()) { /* _debug_draw_cluster(p_render_buffers); - RENDER_TIMESTAMP("Tonemap"); _render_buffers_post_process_and_tonemap(&render_data); */ _render_buffers_debug_draw(p_render_buffers, p_shadow_atlas, p_occluder_debug_tex); if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SDFGI && rb != nullptr && rb->sdfgi != nullptr) { - rb->sdfgi->debug_draw(render_data.cam_projection, render_data.cam_transform, rb->width, rb->height, rb->render_target, rb->texture); + Vector<RID> view_rids; + + for (int v = 0; v < rb->views.size(); v++) { + view_rids.push_back(rb->views[v].view_texture); + } + + rb->sdfgi->debug_draw(render_data.view_count, render_data.view_projection, render_data.cam_transform, rb->width, rb->height, rb->render_target, rb->texture, view_rids); } } } @@ -5366,9 +5466,9 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, Rect2 atlas_rect_norm = atlas_rect; atlas_rect_norm.position /= float(atlas_size); atlas_rect_norm.size /= float(atlas_size); - storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, atlas_rect.size, light_projection.get_z_near(), light_projection.get_z_far(), false); + copy_effects->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, atlas_rect.size, light_projection.get_z_near(), light_projection.get_z_far(), false); atlas_rect_norm.position += Vector2(dual_paraboloid_offset) * atlas_rect_norm.size; - storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, atlas_rect.size, light_projection.get_z_near(), light_projection.get_z_far(), true); + copy_effects->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, atlas_rect.size, light_projection.get_z_near(), light_projection.get_z_far(), true); //restore transform so it can be properly used light_instance_set_shadow_transform(p_light, CameraMatrix(), light_instance->transform, zfar, 0, 0, 0); @@ -5445,7 +5545,7 @@ bool RendererSceneRenderRD::free(RID p_rid) { } else if (lightmap_instance_owner.owns(p_rid)) { lightmap_instance_owner.free(p_rid); } else if (gi.voxel_gi_instance_owner.owns(p_rid)) { - RendererSceneGIRD::VoxelGIInstance *voxel_gi = gi.voxel_gi_instance_owner.get_or_null(p_rid); + RendererRD::GI::VoxelGIInstance *voxel_gi = gi.voxel_gi_instance_owner.get_or_null(p_rid); if (voxel_gi->texture.is_valid()) { RD::get_singleton()->free(voxel_gi->texture); RD::get_singleton()->free(voxel_gi->write_buffer); @@ -5464,8 +5564,8 @@ bool RendererSceneRenderRD::free(RID p_rid) { LightInstance *light_instance = light_instance_owner.get_or_null(p_rid); //remove from shadow atlases.. - for (Set<RID>::Element *E = light_instance->shadow_atlases.front(); E; E = E->next()) { - ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(E->get()); + for (const RID &E : light_instance->shadow_atlases) { + ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(E); ERR_CONTINUE(!shadow_atlas->shadow_owners.has(p_rid)); uint32_t key = shadow_atlas->shadow_owners[p_rid]; uint32_t q = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3; @@ -5656,6 +5756,10 @@ int RendererSceneRenderRD::get_max_directional_lights() const { return cluster.max_directional_lights; } +bool RendererSceneRenderRD::is_vrs_supported() const { + return RD::get_singleton()->has_feature(RD::SUPPORTS_ATTACHMENT_VRS); +} + bool RendererSceneRenderRD::is_dynamic_gi_supported() const { // usable by default (unless low end = true) return true; @@ -5675,8 +5779,7 @@ uint32_t RendererSceneRenderRD::get_max_elements() const { return GLOBAL_GET("rendering/limits/cluster_builder/max_clustered_elements"); } -RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) { - storage = p_storage; +RendererSceneRenderRD::RendererSceneRenderRD() { singleton = this; } @@ -5690,12 +5793,12 @@ void RendererSceneRenderRD::init() { /* SKY SHADER */ - sky.init(storage); + sky.init(); /* GI */ if (is_dynamic_gi_supported()) { - gi.init(storage, &sky); + gi.init(&sky); } { //decals @@ -5881,8 +5984,8 @@ void fog() { directional_soft_shadow_kernel = memnew_arr(float, 128); penumbra_shadow_kernel = memnew_arr(float, 128); soft_shadow_kernel = memnew_arr(float, 128); - shadows_quality_set(RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/shadows/soft_shadow_quality")))); - directional_shadow_quality_set(RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/directional_shadow/soft_shadow_quality")))); + positional_soft_shadow_filter_set_quality(RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/positional_shadow/soft_shadow_filter_quality")))); + directional_soft_shadow_filter_set_quality(RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/directional_shadow/soft_shadow_filter_quality")))); environment_set_volumetric_fog_volume_size(GLOBAL_GET("rendering/environment/volumetric_fog/volume_size"), GLOBAL_GET("rendering/environment/volumetric_fog/volume_depth")); environment_set_volumetric_fog_filter_active(GLOBAL_GET("rendering/environment/volumetric_fog/use_filter")); @@ -5896,6 +5999,7 @@ void fog() { bokeh_dof = memnew(RendererRD::BokehDOF(!can_use_storage)); copy_effects = memnew(RendererRD::CopyEffects(!can_use_storage)); tone_mapper = memnew(RendererRD::ToneMapper); + vrs = memnew(RendererRD::VRS); } RendererSceneRenderRD::~RendererSceneRenderRD() { @@ -5910,6 +6014,9 @@ RendererSceneRenderRD::~RendererSceneRenderRD() { if (tone_mapper) { memdelete(tone_mapper); } + if (vrs) { + memdelete(vrs); + } for (const KeyValue<int, ShadowCubemap> &E : shadow_cubemaps) { RD::get_singleton()->free(E.value.cubemap); diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index f60b7c7232..d11bbd183e 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -38,10 +38,10 @@ #include "servers/rendering/renderer_rd/effects/bokeh_dof.h" #include "servers/rendering/renderer_rd/effects/copy_effects.h" #include "servers/rendering/renderer_rd/effects/tone_mapper.h" +#include "servers/rendering/renderer_rd/effects/vrs.h" +#include "servers/rendering/renderer_rd/environment/gi.h" #include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h" -#include "servers/rendering/renderer_rd/renderer_scene_gi_rd.h" #include "servers/rendering/renderer_rd/renderer_scene_sky_rd.h" -#include "servers/rendering/renderer_rd/renderer_storage_rd.h" #include "servers/rendering/renderer_rd/shaders/volumetric_fog.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl.gen.h" #include "servers/rendering/renderer_scene.h" @@ -53,12 +53,19 @@ struct RenderDataRD { Transform3D cam_transform; CameraMatrix cam_projection; + Vector2 taa_jitter; bool cam_orthogonal = false; // For stereo rendering uint32_t view_count = 1; + Vector3 view_eye_offset[RendererSceneRender::MAX_RENDER_VIEWS]; CameraMatrix view_projection[RendererSceneRender::MAX_RENDER_VIEWS]; + Transform3D prev_cam_transform; + CameraMatrix prev_cam_projection; + Vector2 prev_taa_jitter; + CameraMatrix prev_view_projection[RendererSceneRender::MAX_RENDER_VIEWS]; + float z_near = 0.0; float z_far = 0.0; @@ -92,18 +99,18 @@ struct RenderDataRD { class RendererSceneRenderRD : public RendererSceneRender { friend RendererSceneSkyRD; - friend RendererSceneGIRD; + friend RendererRD::GI; protected: - RendererStorageRD *storage = nullptr; RendererRD::BokehDOF *bokeh_dof = nullptr; RendererRD::CopyEffects *copy_effects = nullptr; RendererRD::ToneMapper *tone_mapper = nullptr; + RendererRD::VRS *vrs = nullptr; double time = 0.0; double time_step = 0.0; struct RenderBufferData { - virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, uint32_t p_view_count) = 0; + virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count, RID p_vrs_texture) = 0; virtual ~RenderBufferData() {} }; virtual RenderBufferData *_create_render_buffer_data() = 0; @@ -124,26 +131,27 @@ protected: virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0; virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) = 0; - void _debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform); + void _debug_sdfgi_probes(RID p_render_buffers, RID p_framebuffer, uint32_t p_view_count, const CameraMatrix *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth); void _debug_draw_cluster(RID p_render_buffers); RenderBufferData *render_buffers_get_data(RID p_render_buffers); virtual void _base_uniforms_changed() = 0; virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) = 0; + virtual RID _render_buffers_get_velocity_texture(RID p_render_buffers) = 0; void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection); void _process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive); void _process_sss(RID p_render_buffers, const CameraMatrix &p_camera); void _process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection, const Transform3D &p_transform); void _copy_framebuffer_to_ssil(RID p_render_buffers); - void _ensure_ss_effects(RID p_render_buffers, bool p_using_ssil); + void _process_taa(RID p_render_buffers, RID p_velocity_buffer, float p_z_near, float p_z_far); bool _needs_post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi); void _post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi); void _pre_resolve_render(RenderDataRD *p_render_data, bool p_use_gi); - void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer); + void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, const RID *p_vrs_slices); void _render_buffers_copy_screen_texture(const RenderDataRD *p_render_data); void _render_buffers_copy_depth_texture(const RenderDataRD *p_render_data); @@ -155,7 +163,7 @@ protected: PagedArrayPool<GeometryInstance *> cull_argument_pool; PagedArray<GeometryInstance *> cull_argument; //need this to exist - RendererSceneGIRD gi; + RendererRD::GI gi; RendererSceneSkyRD sky; RendererSceneEnvironmentRD *get_environment(RID p_environment) { @@ -297,7 +305,7 @@ private: RID depth; RID fb; //for copying - Map<RID, uint32_t> shadow_owners; + HashMap<RID, uint32_t> shadow_owners; }; RID_Owner<ShadowAtlas> shadow_atlas_owner; @@ -345,7 +353,7 @@ private: RID side_fb[6]; }; - Map<int, ShadowCubemap> shadow_cubemaps; + HashMap<int, ShadowCubemap> shadow_cubemaps; ShadowCubemap *_get_shadow_cubemap(int p_size); void _create_shadow_cubemaps(); @@ -387,7 +395,7 @@ private: Rect2 directional_rect; - Set<RID> shadow_atlases; //shadow atlases where this light is registered + HashSet<RID> shadow_atlases; //shadow atlases where this light is registered ForwardID forward_id = -1; @@ -472,6 +480,7 @@ private: float fsr_sharpness = 0.2f; RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED; RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED; + bool use_taa = false; bool use_debanding = false; uint32_t view_count = 1; @@ -485,6 +494,8 @@ private: RID depth_texture; //main depth texture RID texture_fb; // framebuffer for the main texture, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!! RID upscale_texture; //used when upscaling internal_texture (This uses the same resource as internal_texture if there is no upscaling) + RID vrs_texture; // texture for vrs. + RID vrs_fb; // framebuffer to write to our vrs texture // Access to the layers for each of our views (specifically needed for applying post effects on stereoscopic images) struct View { @@ -494,9 +505,9 @@ private: }; Vector<View> views; - RendererSceneGIRD::SDFGI *sdfgi = nullptr; + RendererRD::GI::SDFGI *sdfgi = nullptr; VolumetricFog *volumetric_fog = nullptr; - RendererSceneGIRD::RenderBuffersGI gi; + RendererRD::GI::RenderBuffersGI rbgi; ClusterBuilderRD *cluster_builder = nullptr; @@ -592,8 +603,11 @@ private: RID blur_radius[2]; } ssr; - RID ambient_buffer; - RID reflection_buffer; + struct TAA { + RID history; + RID temp; + RID prev_velocity; // Last frame velocity buffer + } taa; }; /* GI */ @@ -787,14 +801,13 @@ private: RID fog_uniform_set; RID copy_uniform_set; + RID process_uniform_set_density; RID process_uniform_set; RID process_uniform_set2; RID sdfgi_uniform_set; RID sky_uniform_set; int last_shadow_filter = -1; - - Transform3D prev_cam_transform; }; struct VolumetricFogShader { @@ -914,14 +927,14 @@ private: Vector3i _point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform); void _volumetric_fog_erase(RenderBuffers *rb); - void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes); + void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes); struct FogShaderData : public RendererRD::ShaderData { bool valid = false; RID version; RID pipeline; - Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; + HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<uint32_t> ubo_offsets; @@ -929,7 +942,7 @@ private: String path; String code; - Map<StringName, Map<int, RID>> default_texture_params; + HashMap<StringName, HashMap<int, RID>> default_texture_params; bool uses_time = false; @@ -954,7 +967,7 @@ private: virtual void set_render_priority(int p_priority) {} virtual void set_next_pass(RID p_pass) {} - virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); + virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); virtual ~FogMaterialData(); }; @@ -984,6 +997,10 @@ public: virtual Transform3D geometry_instance_get_transform(GeometryInstance *p_instance) = 0; virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance) = 0; + /* GI */ + + RendererRD::GI *get_gi() { return &gi; } + /* SHADOW ATLAS API */ virtual RID shadow_atlas_create() override; @@ -1385,7 +1402,7 @@ public: virtual RD::DataFormat _render_buffers_get_color_format(); virtual bool _render_buffers_can_be_storage(); virtual RID render_buffers_create() override; - virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding, uint32_t p_view_count) override; + virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override; virtual void gi_set_use_half_resolution(bool p_enable) override; RID render_buffers_get_depth_texture(RID p_render_buffers); @@ -1419,7 +1436,7 @@ public: virtual void update_uniform_sets(){}; - virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override; + virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override; virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; @@ -1441,8 +1458,8 @@ public: RS::SubSurfaceScatteringQuality sub_surface_scattering_get_quality() const; virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override; - virtual void shadows_quality_set(RS::ShadowQuality p_quality) override; - virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) override; + virtual void positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override; + virtual void directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override; virtual void decals_set_filter(RS::DecalFilter p_filter) override; virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override; @@ -1490,6 +1507,7 @@ public: virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override; + virtual bool is_vrs_supported() const; virtual bool is_dynamic_gi_supported() const; virtual bool is_clustered_enabled() const; virtual bool is_volumetric_supported() const; @@ -1497,7 +1515,7 @@ public: void init(); - RendererSceneRenderRD(RendererStorageRD *p_storage); + RendererSceneRenderRD(); ~RendererSceneRenderRD(); }; diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp index 4e62dee6af..73175d3cf3 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp @@ -37,6 +37,7 @@ #include "servers/rendering/renderer_rd/storage_rd/material_storage.h" #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/rendering_server_default.h" +#include "servers/rendering/rendering_server_globals.h" //////////////////////////////////////////////////////////////////////////////// // SKY SHADER @@ -151,14 +152,14 @@ void RendererSceneSkyRD::SkyShaderData::set_default_texture_param(const StringNa } } else { if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = Map<int, RID>(); + default_texture_params[p_name] = HashMap<int, RID>(); } default_texture_params[p_name][p_index] = p_texture; } } void RendererSceneSkyRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { - Map<int, StringName> order; + HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { @@ -237,7 +238,7 @@ RendererSceneSkyRD::SkyShaderData::~SkyShaderData() { //////////////////////////////////////////////////////////////////////////////// // Sky material -bool RendererSceneSkyRD::SkyMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +bool RendererSceneSkyRD::SkyMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton); uniform_set_updated = true; @@ -329,13 +330,13 @@ void RendererSceneSkyRD::ReflectionData::clear_reflection_data() { coefficient_buffer = RID(); } -void RendererSceneSkyRD::ReflectionData::update_reflection_data(RendererStorageRD *p_storage, int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers, RD::DataFormat p_texture_format) { +void RendererSceneSkyRD::ReflectionData::update_reflection_data(int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers, RD::DataFormat p_texture_format) { //recreate radiance and all data int mipmaps = p_mipmaps; uint32_t w = p_size, h = p_size; - EffectsRD *effects = p_storage->get_effects(); + EffectsRD *effects = RendererCompositorRD::singleton->get_effects(); ERR_FAIL_NULL_MSG(effects, "Effects haven't been initialised"); bool prefer_raster_effects = effects->get_prefer_raster_effects(); @@ -437,20 +438,20 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(RendererStorageR } } -void RendererSceneSkyRD::ReflectionData::create_reflection_fast_filter(RendererStorageRD *p_storage, bool p_use_arrays) { - EffectsRD *effects = p_storage->get_effects(); - ERR_FAIL_NULL_MSG(effects, "Effects haven't been initialised"); - bool prefer_raster_effects = effects->get_prefer_raster_effects(); +void RendererSceneSkyRD::ReflectionData::create_reflection_fast_filter(bool p_use_arrays) { + RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); + ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialised"); + bool prefer_raster_effects = copy_effects->get_prefer_raster_effects(); if (prefer_raster_effects) { RD::get_singleton()->draw_command_begin_label("Downsample radiance map"); for (int k = 0; k < 6; k++) { - effects->cubemap_downsample_raster(radiance_base_cubemap, downsampled_layer.mipmaps[0].framebuffers[k], k, downsampled_layer.mipmaps[0].size); + copy_effects->cubemap_downsample_raster(radiance_base_cubemap, downsampled_layer.mipmaps[0].framebuffers[k], k, downsampled_layer.mipmaps[0].size); } for (int i = 1; i < downsampled_layer.mipmaps.size(); i++) { for (int k = 0; k < 6; k++) { - effects->cubemap_downsample_raster(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].framebuffers[k], k, downsampled_layer.mipmaps[i].size); + copy_effects->cubemap_downsample_raster(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].framebuffers[k], k, downsampled_layer.mipmaps[i].size); } } RD::get_singleton()->draw_command_end_label(); // Downsample Radiance @@ -459,24 +460,24 @@ void RendererSceneSkyRD::ReflectionData::create_reflection_fast_filter(RendererS RD::get_singleton()->draw_command_begin_label("filter radiance map into array heads"); for (int i = 0; i < layers.size(); i++) { for (int k = 0; k < 6; k++) { - effects->cubemap_filter_raster(downsampled_radiance_cubemap, layers[i].mipmaps[0].framebuffers[k], k, i); + copy_effects->cubemap_filter_raster(downsampled_radiance_cubemap, layers[i].mipmaps[0].framebuffers[k], k, i); } } } else { RD::get_singleton()->draw_command_begin_label("filter radiance map into mipmaps directly"); for (int j = 0; j < layers[0].mipmaps.size(); j++) { for (int k = 0; k < 6; k++) { - effects->cubemap_filter_raster(downsampled_radiance_cubemap, layers[0].mipmaps[j].framebuffers[k], k, j); + copy_effects->cubemap_filter_raster(downsampled_radiance_cubemap, layers[0].mipmaps[j].framebuffers[k], k, j); } } } RD::get_singleton()->draw_command_end_label(); // Filter radiance } else { RD::get_singleton()->draw_command_begin_label("Downsample radiance map"); - effects->cubemap_downsample(radiance_base_cubemap, downsampled_layer.mipmaps[0].view, downsampled_layer.mipmaps[0].size); + copy_effects->cubemap_downsample(radiance_base_cubemap, downsampled_layer.mipmaps[0].view, downsampled_layer.mipmaps[0].size); for (int i = 1; i < downsampled_layer.mipmaps.size(); i++) { - effects->cubemap_downsample(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].view, downsampled_layer.mipmaps[i].size); + copy_effects->cubemap_downsample(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].view, downsampled_layer.mipmaps[i].size); } RD::get_singleton()->draw_command_end_label(); // Downsample Radiance Vector<RID> views; @@ -490,26 +491,26 @@ void RendererSceneSkyRD::ReflectionData::create_reflection_fast_filter(RendererS } } RD::get_singleton()->draw_command_begin_label("Fast filter radiance"); - effects->cubemap_filter(downsampled_radiance_cubemap, views, p_use_arrays); + copy_effects->cubemap_filter(downsampled_radiance_cubemap, views, p_use_arrays); RD::get_singleton()->draw_command_end_label(); // Filter radiance } } -void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(RendererStorageRD *p_storage, bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality) { - EffectsRD *effects = p_storage->get_effects(); - ERR_FAIL_NULL_MSG(effects, "Effects haven't been initialised"); - bool prefer_raster_effects = effects->get_prefer_raster_effects(); +void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality) { + RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); + ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialised"); + bool prefer_raster_effects = copy_effects->get_prefer_raster_effects(); if (prefer_raster_effects) { if (p_base_layer == 1) { RD::get_singleton()->draw_command_begin_label("Downsample radiance map"); for (int k = 0; k < 6; k++) { - effects->cubemap_downsample_raster(radiance_base_cubemap, downsampled_layer.mipmaps[0].framebuffers[k], k, downsampled_layer.mipmaps[0].size); + copy_effects->cubemap_downsample_raster(radiance_base_cubemap, downsampled_layer.mipmaps[0].framebuffers[k], k, downsampled_layer.mipmaps[0].size); } for (int i = 1; i < downsampled_layer.mipmaps.size(); i++) { for (int k = 0; k < 6; k++) { - effects->cubemap_downsample_raster(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].framebuffers[k], k, downsampled_layer.mipmaps[i].size); + copy_effects->cubemap_downsample_raster(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].framebuffers[k], k, downsampled_layer.mipmaps[i].size); } } RD::get_singleton()->draw_command_end_label(); // Downsample Radiance @@ -518,7 +519,7 @@ void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(Ren RD::get_singleton()->draw_command_begin_label("High Quality filter radiance"); if (p_use_arrays) { for (int k = 0; k < 6; k++) { - effects->cubemap_roughness_raster( + copy_effects->cubemap_roughness_raster( downsampled_radiance_cubemap, layers[p_base_layer].mipmaps[0].framebuffers[k], k, @@ -528,7 +529,7 @@ void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(Ren } } else { for (int k = 0; k < 6; k++) { - effects->cubemap_roughness_raster( + copy_effects->cubemap_roughness_raster( downsampled_radiance_cubemap, layers[0].mipmaps[p_base_layer].framebuffers[k], k, @@ -540,19 +541,19 @@ void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(Ren } else { if (p_base_layer == 1) { RD::get_singleton()->draw_command_begin_label("Downsample radiance map"); - effects->cubemap_downsample(radiance_base_cubemap, downsampled_layer.mipmaps[0].view, downsampled_layer.mipmaps[0].size); + copy_effects->cubemap_downsample(radiance_base_cubemap, downsampled_layer.mipmaps[0].view, downsampled_layer.mipmaps[0].size); for (int i = 1; i < downsampled_layer.mipmaps.size(); i++) { - effects->cubemap_downsample(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].view, downsampled_layer.mipmaps[i].size); + copy_effects->cubemap_downsample(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].view, downsampled_layer.mipmaps[i].size); } RD::get_singleton()->draw_command_end_label(); // Downsample Radiance } RD::get_singleton()->draw_command_begin_label("High Quality filter radiance"); if (p_use_arrays) { - effects->cubemap_roughness(downsampled_radiance_cubemap, layers[p_base_layer].views[0], p_cube_side, p_sky_ggx_samples_quality, float(p_base_layer) / (layers.size() - 1.0), layers[p_base_layer].mipmaps[0].size.x); + copy_effects->cubemap_roughness(downsampled_radiance_cubemap, layers[p_base_layer].views[0], p_cube_side, p_sky_ggx_samples_quality, float(p_base_layer) / (layers.size() - 1.0), layers[p_base_layer].mipmaps[0].size.x); } else { - effects->cubemap_roughness( + copy_effects->cubemap_roughness( downsampled_radiance_cubemap, layers[0].views[p_base_layer], p_cube_side, @@ -564,10 +565,10 @@ void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(Ren RD::get_singleton()->draw_command_end_label(); // Filter radiance } -void RendererSceneSkyRD::ReflectionData::update_reflection_mipmaps(RendererStorageRD *p_storage, int p_start, int p_end) { - EffectsRD *effects = p_storage->get_effects(); - ERR_FAIL_NULL_MSG(effects, "Effects haven't been initialised"); - bool prefer_raster_effects = effects->get_prefer_raster_effects(); +void RendererSceneSkyRD::ReflectionData::update_reflection_mipmaps(int p_start, int p_end) { + RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton(); + ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialised"); + bool prefer_raster_effects = copy_effects->get_prefer_raster_effects(); RD::get_singleton()->draw_command_begin_label("Update Radiance Cubemap Array Mipmaps"); for (int i = p_start; i < p_end; i++) { @@ -577,11 +578,11 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_mipmaps(RendererStora if (prefer_raster_effects) { for (int k = 0; k < 6; k++) { RID framebuffer = layers[i].mipmaps[j + 1].framebuffers[k]; - effects->cubemap_downsample_raster(view, framebuffer, k, size); + copy_effects->cubemap_downsample_raster(view, framebuffer, k, size); } } else { RID texture = layers[i].views[j + 1]; - effects->cubemap_downsample(view, texture, size); + copy_effects->cubemap_downsample(view, texture, size); } } } @@ -591,7 +592,7 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_mipmaps(RendererStora //////////////////////////////////////////////////////////////////////////////// // RendererSceneSkyRD::Sky -void RendererSceneSkyRD::Sky::free(RendererStorageRD *p_storage) { +void RendererSceneSkyRD::Sky::free() { if (radiance.is_valid()) { RD::get_singleton()->free(radiance); radiance = RID(); @@ -614,12 +615,12 @@ void RendererSceneSkyRD::Sky::free(RendererStorageRD *p_storage) { } if (material.is_valid()) { - p_storage->free(material); + RSG::material_storage->material_free(material); material = RID(); } } -RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextureSetVersion p_version, RID p_default_shader_rd) { +RID RendererSceneSkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); if (texture_uniform_sets[p_version].is_valid() && RD::get_singleton()->uniform_set_is_valid(texture_uniform_sets[p_version])) { @@ -795,10 +796,9 @@ RendererSceneSkyRD::RendererSceneSkyRD() { sky_use_cubemap_array = GLOBAL_GET("rendering/reflections/sky_reflections/texture_array_reflections"); } -void RendererSceneSkyRD::init(RendererStorageRD *p_storage) { +void RendererSceneSkyRD::init() { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - storage = p_storage; { // Start with the directional lights for the sky @@ -846,6 +846,7 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) { actions.renames["POSITION"] = "params.position_multiplier.xyz"; actions.renames["SKY_COORDS"] = "panorama_coords"; actions.renames["SCREEN_UV"] = "uv"; + actions.renames["FRAGCOORD"] = "gl_FragCoord"; actions.renames["TIME"] = "params.time"; actions.renames["PI"] = _MKSTR(Math_PI); actions.renames["TAU"] = _MKSTR(Math_TAU); @@ -1386,7 +1387,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM for (int i = 0; i < 6; i++) { Basis local_view = Basis::looking_at(view_normals[i], view_up[i]); - RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES, sky_shader.default_shader_rd); + RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES, sky_shader.default_shader_rd); cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[2].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin, p_luminance_multiplier); @@ -1405,7 +1406,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM for (int i = 0; i < 6; i++) { Basis local_view = Basis::looking_at(view_normals[i], view_up[i]); - RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP_HALF_RES, sky_shader.default_shader_rd); + RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP_HALF_RES, sky_shader.default_shader_rd); cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[1].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin, p_luminance_multiplier); @@ -1420,7 +1421,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM RD::get_singleton()->draw_command_begin_label("Render Sky Cubemap"); for (int i = 0; i < 6; i++) { Basis local_view = Basis::looking_at(view_normals[i], view_up[i]); - RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP, sky_shader.default_shader_rd); + RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP, sky_shader.default_shader_rd); cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[0].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin, p_luminance_multiplier); @@ -1429,22 +1430,22 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM RD::get_singleton()->draw_command_end_label(); if (sky_mode == RS::SKY_MODE_REALTIME) { - sky->reflection.create_reflection_fast_filter(storage, sky_use_cubemap_array); + sky->reflection.create_reflection_fast_filter(sky_use_cubemap_array); if (sky_use_cubemap_array) { - sky->reflection.update_reflection_mipmaps(storage, 0, sky->reflection.layers.size()); + sky->reflection.update_reflection_mipmaps(0, sky->reflection.layers.size()); } } else { if (update_single_frame) { for (int i = 1; i < max_processing_layer; i++) { - sky->reflection.create_reflection_importance_sample(storage, sky_use_cubemap_array, 10, i, sky_ggx_samples_quality); + sky->reflection.create_reflection_importance_sample(sky_use_cubemap_array, 10, i, sky_ggx_samples_quality); } if (sky_use_cubemap_array) { - sky->reflection.update_reflection_mipmaps(storage, 0, sky->reflection.layers.size()); + sky->reflection.update_reflection_mipmaps(0, sky->reflection.layers.size()); } } else { if (sky_use_cubemap_array) { // Multi-Frame so just update the first array level - sky->reflection.update_reflection_mipmaps(storage, 0, 1); + sky->reflection.update_reflection_mipmaps(0, 1); } } sky->processing_layer = 1; @@ -1454,10 +1455,10 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM } else { if (sky_mode == RS::SKY_MODE_INCREMENTAL && sky->processing_layer < max_processing_layer) { - sky->reflection.create_reflection_importance_sample(storage, sky_use_cubemap_array, 10, sky->processing_layer, sky_ggx_samples_quality); + sky->reflection.create_reflection_importance_sample(sky_use_cubemap_array, 10, sky->processing_layer, sky_ggx_samples_quality); if (sky_use_cubemap_array) { - sky->reflection.update_reflection_mipmaps(storage, sky->processing_layer, sky->processing_layer + 1); + sky->reflection.update_reflection_mipmaps(sky->processing_layer, sky->processing_layer + 1); } sky->processing_layer++; @@ -1530,12 +1531,12 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont projections = &camera; } - sky_transform = p_transform.basis * sky_transform; + sky_transform = sky_transform * p_transform.basis; if (shader_data->uses_quarter_res) { PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_QUARTER_RES_MULTIVIEW : SKY_VERSION_QUARTER_RES]; - RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_QUARTER_RES, sky_shader.default_shader_rd); + RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_QUARTER_RES, sky_shader.default_shader_rd); Vector<Color> clear_colors; clear_colors.push_back(Color(0.0, 0.0, 0.0)); @@ -1548,7 +1549,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont if (shader_data->uses_half_res) { PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_HALF_RES_MULTIVIEW : SKY_VERSION_HALF_RES]; - RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_HALF_RES, sky_shader.default_shader_rd); + RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_HALF_RES, sky_shader.default_shader_rd); Vector<Color> clear_colors; clear_colors.push_back(Color(0.0, 0.0, 0.0)); @@ -1562,7 +1563,7 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont RID texture_uniform_set; if (sky) { - texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_BACKGROUND, sky_shader.default_shader_rd); + texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_BACKGROUND, sky_shader.default_shader_rd); } else { texture_uniform_set = sky_scene_state.fog_only_texture_uniform_set; } @@ -1633,7 +1634,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u if (shader_data->uses_quarter_res) { PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_QUARTER_RES_MULTIVIEW : SKY_VERSION_QUARTER_RES]; - RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_QUARTER_RES, sky_shader.default_shader_rd); + RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_QUARTER_RES, sky_shader.default_shader_rd); Vector<Color> clear_colors; clear_colors.push_back(Color(0.0, 0.0, 0.0)); @@ -1646,7 +1647,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u if (shader_data->uses_half_res) { PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_HALF_RES_MULTIVIEW : SKY_VERSION_HALF_RES]; - RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_HALF_RES, sky_shader.default_shader_rd); + RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_HALF_RES, sky_shader.default_shader_rd); Vector<Color> clear_colors; clear_colors.push_back(Color(0.0, 0.0, 0.0)); @@ -1728,7 +1729,7 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme RID texture_uniform_set; if (sky) { - texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_BACKGROUND, sky_shader.default_shader_rd); + texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_BACKGROUND, sky_shader.default_shader_rd); } else { texture_uniform_set = sky_scene_state.fog_only_texture_uniform_set; } @@ -1776,7 +1777,7 @@ void RendererSceneSkyRD::update_dirty_skys() { sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView()); - sky->reflection.update_reflection_data(storage, sky->radiance_size, mipmaps, true, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers, texture_format); + sky->reflection.update_reflection_data(sky->radiance_size, mipmaps, true, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers, texture_format); } else { //regular cubemap, lower quality (aliasing, less memory) @@ -1791,7 +1792,7 @@ void RendererSceneSkyRD::update_dirty_skys() { sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView()); - sky->reflection.update_reflection_data(storage, sky->radiance_size, MIN(mipmaps, layers), false, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers, texture_format); + sky->reflection.update_reflection_data(sky->radiance_size, MIN(mipmaps, layers), false, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers, texture_format); } texture_set_dirty = true; } @@ -1871,7 +1872,7 @@ void RendererSceneSkyRD::free_sky(RID p_sky) { Sky *sky = get_sky(p_sky); ERR_FAIL_COND(!sky); - sky->free(storage); + sky->free(); sky_owner.free(p_sky); } diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h index ec225019c8..a8ee406abc 100644 --- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_sky_rd.h @@ -33,11 +33,13 @@ #include "core/templates/rid_owner.h" #include "servers/rendering/renderer_compositor.h" +#include "servers/rendering/renderer_rd/pipeline_cache_rd.h" #include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h" -#include "servers/rendering/renderer_rd/renderer_storage_rd.h" #include "servers/rendering/renderer_rd/shaders/sky.glsl.gen.h" +#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" #include "servers/rendering/renderer_scene_render.h" #include "servers/rendering/rendering_device.h" +#include "servers/rendering/shader_compiler.h" // Forward declare RendererSceneRenderRD so we can pass it into some of our methods, these classes are pretty tightly bound class RendererSceneRenderRD; @@ -63,7 +65,6 @@ public: }; private: - RendererStorageRD *storage = nullptr; RD::DataFormat texture_format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; RID index_buffer; @@ -110,7 +111,7 @@ private: RID version; PipelineCacheRD pipelines[SKY_VERSION_MAX]; - Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; + HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<uint32_t> ubo_offsets; @@ -118,7 +119,7 @@ private: String path; String code; - Map<StringName, Map<int, RID>> default_texture_params; + HashMap<StringName, HashMap<int, RID>> default_texture_params; bool uses_time = false; bool uses_position = false; @@ -211,10 +212,10 @@ public: Vector<Layer> layers; void clear_reflection_data(); - void update_reflection_data(RendererStorageRD *p_storage, int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers, RD::DataFormat p_texture_format); - void create_reflection_fast_filter(RendererStorageRD *p_storage, bool p_use_arrays); - void create_reflection_importance_sample(RendererStorageRD *p_storage, bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality); - void update_reflection_mipmaps(RendererStorageRD *p_storage, int p_start, int p_end); + void update_reflection_data(int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers, RD::DataFormat p_texture_format); + void create_reflection_fast_filter(bool p_use_arrays); + void create_reflection_importance_sample(bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality); + void update_reflection_mipmaps(int p_start, int p_end); }; /* Sky shader */ @@ -235,7 +236,7 @@ public: virtual void set_render_priority(int p_priority) {} virtual void set_next_pass(RID p_pass) {} - virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); + virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); virtual ~SkyMaterialData(); }; @@ -267,9 +268,9 @@ public: Vector3 prev_position; float prev_time; - void free(RendererStorageRD *p_storage); + void free(); - RID get_textures(RendererStorageRD *p_storage, SkyTextureSetVersion p_version, RID p_default_shader_rd); + RID get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd); bool set_radiance_size(int p_radiance_size); bool set_mode(RS::SkyMode p_mode); bool set_material(RID p_material); @@ -289,7 +290,7 @@ public: static RendererRD::MaterialData *_create_sky_material_funcs(RendererRD::ShaderData *p_shader); RendererSceneSkyRD(); - void init(RendererStorageRD *p_storage); + void init(); void set_texture_format(RD::DataFormat p_texture_format); ~RendererSceneSkyRD(); diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp deleted file mode 100644 index cf642c38c9..0000000000 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ /dev/null @@ -1,745 +0,0 @@ -/*************************************************************************/ -/* renderer_storage_rd.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "renderer_storage_rd.h" - -#include "core/config/engine.h" -#include "core/config/project_settings.h" -#include "core/io/resource_loader.h" -#include "core/math/math_defs.h" -#include "renderer_compositor_rd.h" -#include "servers/rendering/renderer_rd/storage_rd/light_storage.h" -#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h" -#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h" -#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" -#include "servers/rendering/rendering_server_globals.h" -#include "servers/rendering/shader_language.h" - -/* FOG VOLUMES */ - -RID RendererStorageRD::fog_volume_allocate() { - return fog_volume_owner.allocate_rid(); -} -void RendererStorageRD::fog_volume_initialize(RID p_rid) { - fog_volume_owner.initialize_rid(p_rid, FogVolume()); -} - -void RendererStorageRD::fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) { - FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); - ERR_FAIL_COND(!fog_volume); - - if (p_shape == fog_volume->shape) { - return; - } - - fog_volume->shape = p_shape; - fog_volume->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); -} - -void RendererStorageRD::fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) { - FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); - ERR_FAIL_COND(!fog_volume); - - fog_volume->extents = p_extents; - fog_volume->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); -} - -void RendererStorageRD::fog_volume_set_material(RID p_fog_volume, RID p_material) { - FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); - ERR_FAIL_COND(!fog_volume); - fog_volume->material = p_material; -} - -RID RendererStorageRD::fog_volume_get_material(RID p_fog_volume) const { - FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); - ERR_FAIL_COND_V(!fog_volume, RID()); - - return fog_volume->material; -} - -RS::FogVolumeShape RendererStorageRD::fog_volume_get_shape(RID p_fog_volume) const { - FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); - ERR_FAIL_COND_V(!fog_volume, RS::FOG_VOLUME_SHAPE_BOX); - - return fog_volume->shape; -} - -AABB RendererStorageRD::fog_volume_get_aabb(RID p_fog_volume) const { - FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); - ERR_FAIL_COND_V(!fog_volume, AABB()); - - switch (fog_volume->shape) { - case RS::FOG_VOLUME_SHAPE_ELLIPSOID: - case RS::FOG_VOLUME_SHAPE_BOX: { - AABB aabb; - aabb.position = -fog_volume->extents; - aabb.size = fog_volume->extents * 2; - return aabb; - } - default: { - // Need some size otherwise will get culled - return AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2)); - } - } - - return AABB(); -} - -Vector3 RendererStorageRD::fog_volume_get_extents(RID p_fog_volume) const { - const FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume); - ERR_FAIL_COND_V(!fog_volume, Vector3()); - return fog_volume->extents; -} - -/* VISIBILITY NOTIFIER */ - -RID RendererStorageRD::visibility_notifier_allocate() { - return visibility_notifier_owner.allocate_rid(); -} -void RendererStorageRD::visibility_notifier_initialize(RID p_notifier) { - visibility_notifier_owner.initialize_rid(p_notifier, VisibilityNotifier()); -} -void RendererStorageRD::visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) { - VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier); - ERR_FAIL_COND(!vn); - vn->aabb = p_aabb; - vn->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); -} -void RendererStorageRD::visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) { - VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier); - ERR_FAIL_COND(!vn); - vn->enter_callback = p_enter_callbable; - vn->exit_callback = p_exit_callable; -} - -AABB RendererStorageRD::visibility_notifier_get_aabb(RID p_notifier) const { - const VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier); - ERR_FAIL_COND_V(!vn, AABB()); - return vn->aabb; -} -void RendererStorageRD::visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) { - VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier); - ERR_FAIL_COND(!vn); - - if (p_enter) { - if (!vn->enter_callback.is_null()) { - if (p_deferred) { - vn->enter_callback.call_deferred(nullptr, 0); - } else { - Variant r; - Callable::CallError ce; - vn->enter_callback.call(nullptr, 0, r, ce); - } - } - } else { - if (!vn->exit_callback.is_null()) { - if (p_deferred) { - vn->exit_callback.call_deferred(nullptr, 0); - } else { - Variant r; - Callable::CallError ce; - vn->exit_callback.call(nullptr, 0, r, ce); - } - } - } -} - -/* VOXEL GI */ - -RID RendererStorageRD::voxel_gi_allocate() { - return voxel_gi_owner.allocate_rid(); -} -void RendererStorageRD::voxel_gi_initialize(RID p_voxel_gi) { - voxel_gi_owner.initialize_rid(p_voxel_gi, VoxelGI()); -} - -void RendererStorageRD::voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND(!voxel_gi); - - if (voxel_gi->octree_buffer.is_valid()) { - RD::get_singleton()->free(voxel_gi->octree_buffer); - RD::get_singleton()->free(voxel_gi->data_buffer); - if (voxel_gi->sdf_texture.is_valid()) { - RD::get_singleton()->free(voxel_gi->sdf_texture); - } - - voxel_gi->sdf_texture = RID(); - voxel_gi->octree_buffer = RID(); - voxel_gi->data_buffer = RID(); - voxel_gi->octree_buffer_size = 0; - voxel_gi->data_buffer_size = 0; - voxel_gi->cell_count = 0; - } - - voxel_gi->to_cell_xform = p_to_cell_xform; - voxel_gi->bounds = p_aabb; - voxel_gi->octree_size = p_octree_size; - voxel_gi->level_counts = p_level_counts; - - if (p_octree_cells.size()) { - ERR_FAIL_COND(p_octree_cells.size() % 32 != 0); //cells size must be a multiple of 32 - - uint32_t cell_count = p_octree_cells.size() / 32; - - ERR_FAIL_COND(p_data_cells.size() != (int)cell_count * 16); //see that data size matches - - voxel_gi->cell_count = cell_count; - voxel_gi->octree_buffer = RD::get_singleton()->storage_buffer_create(p_octree_cells.size(), p_octree_cells); - voxel_gi->octree_buffer_size = p_octree_cells.size(); - voxel_gi->data_buffer = RD::get_singleton()->storage_buffer_create(p_data_cells.size(), p_data_cells); - voxel_gi->data_buffer_size = p_data_cells.size(); - - if (p_distance_field.size()) { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.width = voxel_gi->octree_size.x; - tf.height = voxel_gi->octree_size.y; - tf.depth = voxel_gi->octree_size.z; - tf.texture_type = RD::TEXTURE_TYPE_3D; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; - Vector<Vector<uint8_t>> s; - s.push_back(p_distance_field); - voxel_gi->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView(), s); - } -#if 0 - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.width = voxel_gi->octree_size.x; - tf.height = voxel_gi->octree_size.y; - tf.depth = voxel_gi->octree_size.z; - tf.type = RD::TEXTURE_TYPE_3D; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; - tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UNORM); - tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UINT); - voxel_gi->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); - } - RID shared_tex; - { - RD::TextureView tv; - tv.format_override = RD::DATA_FORMAT_R8_UINT; - shared_tex = RD::get_singleton()->texture_create_shared(tv, voxel_gi->sdf_texture); - } - //update SDF texture - Vector<RD::Uniform> uniforms; - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 1; - u.append_id(voxel_gi->octree_buffer); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 2; - u.append_id(voxel_gi->data_buffer); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 3; - u.append_id(shared_tex); - uniforms.push_back(u); - } - - RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, voxel_gi_sdf_shader_version_shader, 0); - - { - uint32_t push_constant[4] = { 0, 0, 0, 0 }; - - for (int i = 0; i < voxel_gi->level_counts.size() - 1; i++) { - push_constant[0] += voxel_gi->level_counts[i]; - } - push_constant[1] = push_constant[0] + voxel_gi->level_counts[voxel_gi->level_counts.size() - 1]; - - print_line("offset: " + itos(push_constant[0])); - print_line("size: " + itos(push_constant[1])); - //create SDF - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, voxel_gi_sdf_shader_pipeline); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set, 0); - RD::get_singleton()->compute_list_set_push_constant(compute_list, push_constant, sizeof(uint32_t) * 4); - RD::get_singleton()->compute_list_dispatch(compute_list, voxel_gi->octree_size.x / 4, voxel_gi->octree_size.y / 4, voxel_gi->octree_size.z / 4); - RD::get_singleton()->compute_list_end(); - } - - RD::get_singleton()->free(uniform_set); - RD::get_singleton()->free(shared_tex); - } -#endif - } - - voxel_gi->version++; - voxel_gi->data_version++; - - voxel_gi->dependency.changed_notify(DEPENDENCY_CHANGED_AABB); -} - -AABB RendererStorageRD::voxel_gi_get_bounds(RID p_voxel_gi) const { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, AABB()); - - return voxel_gi->bounds; -} - -Vector3i RendererStorageRD::voxel_gi_get_octree_size(RID p_voxel_gi) const { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, Vector3i()); - return voxel_gi->octree_size; -} - -Vector<uint8_t> RendererStorageRD::voxel_gi_get_octree_cells(RID p_voxel_gi) const { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, Vector<uint8_t>()); - - if (voxel_gi->octree_buffer.is_valid()) { - return RD::get_singleton()->buffer_get_data(voxel_gi->octree_buffer); - } - return Vector<uint8_t>(); -} - -Vector<uint8_t> RendererStorageRD::voxel_gi_get_data_cells(RID p_voxel_gi) const { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, Vector<uint8_t>()); - - if (voxel_gi->data_buffer.is_valid()) { - return RD::get_singleton()->buffer_get_data(voxel_gi->data_buffer); - } - return Vector<uint8_t>(); -} - -Vector<uint8_t> RendererStorageRD::voxel_gi_get_distance_field(RID p_voxel_gi) const { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, Vector<uint8_t>()); - - if (voxel_gi->data_buffer.is_valid()) { - return RD::get_singleton()->texture_get_data(voxel_gi->sdf_texture, 0); - } - return Vector<uint8_t>(); -} - -Vector<int> RendererStorageRD::voxel_gi_get_level_counts(RID p_voxel_gi) const { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, Vector<int>()); - - return voxel_gi->level_counts; -} - -Transform3D RendererStorageRD::voxel_gi_get_to_cell_xform(RID p_voxel_gi) const { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, Transform3D()); - - return voxel_gi->to_cell_xform; -} - -void RendererStorageRD::voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND(!voxel_gi); - - voxel_gi->dynamic_range = p_range; - voxel_gi->version++; -} - -float RendererStorageRD::voxel_gi_get_dynamic_range(RID p_voxel_gi) const { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, 0); - - return voxel_gi->dynamic_range; -} - -void RendererStorageRD::voxel_gi_set_propagation(RID p_voxel_gi, float p_range) { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND(!voxel_gi); - - voxel_gi->propagation = p_range; - voxel_gi->version++; -} - -float RendererStorageRD::voxel_gi_get_propagation(RID p_voxel_gi) const { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, 0); - return voxel_gi->propagation; -} - -void RendererStorageRD::voxel_gi_set_energy(RID p_voxel_gi, float p_energy) { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND(!voxel_gi); - - voxel_gi->energy = p_energy; -} - -float RendererStorageRD::voxel_gi_get_energy(RID p_voxel_gi) const { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, 0); - return voxel_gi->energy; -} - -void RendererStorageRD::voxel_gi_set_bias(RID p_voxel_gi, float p_bias) { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND(!voxel_gi); - - voxel_gi->bias = p_bias; -} - -float RendererStorageRD::voxel_gi_get_bias(RID p_voxel_gi) const { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, 0); - return voxel_gi->bias; -} - -void RendererStorageRD::voxel_gi_set_normal_bias(RID p_voxel_gi, float p_normal_bias) { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND(!voxel_gi); - - voxel_gi->normal_bias = p_normal_bias; -} - -float RendererStorageRD::voxel_gi_get_normal_bias(RID p_voxel_gi) const { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, 0); - return voxel_gi->normal_bias; -} - -void RendererStorageRD::voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND(!voxel_gi); - - voxel_gi->anisotropy_strength = p_strength; -} - -float RendererStorageRD::voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, 0); - return voxel_gi->anisotropy_strength; -} - -void RendererStorageRD::voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND(!voxel_gi); - - voxel_gi->interior = p_enable; -} - -void RendererStorageRD::voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND(!voxel_gi); - - voxel_gi->use_two_bounces = p_enable; - voxel_gi->version++; -} - -bool RendererStorageRD::voxel_gi_is_using_two_bounces(RID p_voxel_gi) const { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, false); - return voxel_gi->use_two_bounces; -} - -bool RendererStorageRD::voxel_gi_is_interior(RID p_voxel_gi) const { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, 0); - return voxel_gi->interior; -} - -uint32_t RendererStorageRD::voxel_gi_get_version(RID p_voxel_gi) { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, 0); - return voxel_gi->version; -} - -uint32_t RendererStorageRD::voxel_gi_get_data_version(RID p_voxel_gi) { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, 0); - return voxel_gi->data_version; -} - -RID RendererStorageRD::voxel_gi_get_octree_buffer(RID p_voxel_gi) const { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, RID()); - return voxel_gi->octree_buffer; -} - -RID RendererStorageRD::voxel_gi_get_data_buffer(RID p_voxel_gi) const { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, RID()); - return voxel_gi->data_buffer; -} - -RID RendererStorageRD::voxel_gi_get_sdf_texture(RID p_voxel_gi) { - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi); - ERR_FAIL_COND_V(!voxel_gi, RID()); - - return voxel_gi->sdf_texture; -} - -/* misc */ - -void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_instance) { - if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_base)) { - RendererRD::Mesh *mesh = RendererRD::MeshStorage::get_singleton()->get_mesh(p_base); - p_instance->update_dependency(&mesh->dependency); - } else if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_base)) { - RendererRD::MultiMesh *multimesh = RendererRD::MeshStorage::get_singleton()->get_multimesh(p_base); - p_instance->update_dependency(&multimesh->dependency); - if (multimesh->mesh.is_valid()) { - base_update_dependency(multimesh->mesh, p_instance); - } - } else if (RendererRD::LightStorage::get_singleton()->owns_reflection_probe(p_base)) { - RendererRD::ReflectionProbe *rp = RendererRD::LightStorage::get_singleton()->get_reflection_probe(p_base); - p_instance->update_dependency(&rp->dependency); - } else if (RendererRD::TextureStorage::get_singleton()->owns_decal(p_base)) { - RendererRD::Decal *decal = RendererRD::TextureStorage::get_singleton()->get_decal(p_base); - p_instance->update_dependency(&decal->dependency); - } else if (voxel_gi_owner.owns(p_base)) { - VoxelGI *gip = voxel_gi_owner.get_or_null(p_base); - p_instance->update_dependency(&gip->dependency); - } else if (RendererRD::LightStorage::get_singleton()->owns_lightmap(p_base)) { - RendererRD::Lightmap *lm = RendererRD::LightStorage::get_singleton()->get_lightmap(p_base); - p_instance->update_dependency(&lm->dependency); - } else if (RendererRD::LightStorage::get_singleton()->owns_light(p_base)) { - RendererRD::Light *l = RendererRD::LightStorage::get_singleton()->get_light(p_base); - p_instance->update_dependency(&l->dependency); - } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles(p_base)) { - RendererRD::Particles *p = RendererRD::ParticlesStorage::get_singleton()->get_particles(p_base); - p_instance->update_dependency(&p->dependency); - } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision(p_base)) { - RendererRD::ParticlesCollision *pc = RendererRD::ParticlesStorage::get_singleton()->get_particles_collision(p_base); - p_instance->update_dependency(&pc->dependency); - } else if (fog_volume_owner.owns(p_base)) { - FogVolume *fv = fog_volume_owner.get_or_null(p_base); - p_instance->update_dependency(&fv->dependency); - } else if (visibility_notifier_owner.owns(p_base)) { - VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_base); - p_instance->update_dependency(&vn->dependency); - } -} - -RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const { - if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_rid)) { - return RS::INSTANCE_MESH; - } - if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_rid)) { - return RS::INSTANCE_MULTIMESH; - } - if (RendererRD::LightStorage::get_singleton()->owns_reflection_probe(p_rid)) { - return RS::INSTANCE_REFLECTION_PROBE; - } - if (RendererRD::TextureStorage::get_singleton()->owns_decal(p_rid)) { - return RS::INSTANCE_DECAL; - } - if (voxel_gi_owner.owns(p_rid)) { - return RS::INSTANCE_VOXEL_GI; - } - if (RendererRD::LightStorage::get_singleton()->owns_light(p_rid)) { - return RS::INSTANCE_LIGHT; - } - if (RendererRD::LightStorage::get_singleton()->owns_lightmap(p_rid)) { - return RS::INSTANCE_LIGHTMAP; - } - if (RendererRD::ParticlesStorage::get_singleton()->owns_particles(p_rid)) { - return RS::INSTANCE_PARTICLES; - } - if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision(p_rid)) { - return RS::INSTANCE_PARTICLES_COLLISION; - } - if (fog_volume_owner.owns(p_rid)) { - return RS::INSTANCE_FOG_VOLUME; - } - if (visibility_notifier_owner.owns(p_rid)) { - return RS::INSTANCE_VISIBLITY_NOTIFIER; - } - - return RS::INSTANCE_NONE; -} - -void RendererStorageRD::update_dirty_resources() { - RendererRD::MaterialStorage::get_singleton()->_update_global_variables(); //must do before materials, so it can queue them for update - RendererRD::MaterialStorage::get_singleton()->_update_queued_materials(); - RendererRD::MeshStorage::get_singleton()->_update_dirty_multimeshes(); - RendererRD::MeshStorage::get_singleton()->_update_dirty_skeletons(); - RendererRD::TextureStorage::get_singleton()->update_decal_atlas(); -} - -bool RendererStorageRD::has_os_feature(const String &p_feature) const { - if (p_feature == "rgtc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC5_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) { - return true; - } - - if (p_feature == "s3tc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) { - return true; - } - - if (p_feature == "bptc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC7_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) { - return true; - } - - if ((p_feature == "etc" || p_feature == "etc2") && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) { - return true; - } - - return false; -} - -bool RendererStorageRD::free(RID p_rid) { - if (RendererRD::TextureStorage::get_singleton()->owns_texture(p_rid)) { - RendererRD::TextureStorage::get_singleton()->texture_free(p_rid); - } else if (RendererRD::TextureStorage::get_singleton()->owns_canvas_texture(p_rid)) { - RendererRD::TextureStorage::get_singleton()->canvas_texture_free(p_rid); - } else if (RendererRD::MaterialStorage::get_singleton()->owns_shader(p_rid)) { - RendererRD::MaterialStorage::get_singleton()->shader_free(p_rid); - } else if (RendererRD::MaterialStorage::get_singleton()->owns_material(p_rid)) { - RendererRD::MaterialStorage::get_singleton()->material_free(p_rid); - } else if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_rid)) { - RendererRD::MeshStorage::get_singleton()->mesh_free(p_rid); - } else if (RendererRD::MeshStorage::get_singleton()->owns_mesh_instance(p_rid)) { - RendererRD::MeshStorage::get_singleton()->mesh_instance_free(p_rid); - } else if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_rid)) { - RendererRD::MeshStorage::get_singleton()->multimesh_free(p_rid); - } else if (RendererRD::MeshStorage::get_singleton()->owns_skeleton(p_rid)) { - RendererRD::MeshStorage::get_singleton()->skeleton_free(p_rid); - } else if (RendererRD::LightStorage::get_singleton()->owns_reflection_probe(p_rid)) { - RendererRD::LightStorage::get_singleton()->reflection_probe_free(p_rid); - } else if (RendererRD::TextureStorage::get_singleton()->owns_decal(p_rid)) { - RendererRD::TextureStorage::get_singleton()->decal_free(p_rid); - } else if (voxel_gi_owner.owns(p_rid)) { - voxel_gi_allocate_data(p_rid, Transform3D(), AABB(), Vector3i(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<int>()); //deallocate - VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_rid); - voxel_gi->dependency.deleted_notify(p_rid); - voxel_gi_owner.free(p_rid); - } else if (RendererRD::LightStorage::get_singleton()->owns_lightmap(p_rid)) { - RendererRD::LightStorage::get_singleton()->lightmap_free(p_rid); - } else if (RendererRD::LightStorage::get_singleton()->owns_light(p_rid)) { - RendererRD::LightStorage::get_singleton()->light_free(p_rid); - } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles(p_rid)) { - RendererRD::ParticlesStorage::get_singleton()->particles_free(p_rid); - } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision(p_rid)) { - RendererRD::ParticlesStorage::get_singleton()->particles_collision_free(p_rid); - } else if (visibility_notifier_owner.owns(p_rid)) { - VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_rid); - vn->dependency.deleted_notify(p_rid); - visibility_notifier_owner.free(p_rid); - } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision_instance(p_rid)) { - RendererRD::ParticlesStorage::get_singleton()->particles_collision_instance_free(p_rid); - } else if (fog_volume_owner.owns(p_rid)) { - FogVolume *fog_volume = fog_volume_owner.get_or_null(p_rid); - fog_volume->dependency.deleted_notify(p_rid); - fog_volume_owner.free(p_rid); - } else if (RendererRD::TextureStorage::get_singleton()->owns_render_target(p_rid)) { - RendererRD::TextureStorage::get_singleton()->render_target_free(p_rid); - } else { - return false; - } - - return true; -} - -void RendererStorageRD::init_effects(bool p_prefer_raster_effects) { - effects = memnew(EffectsRD(p_prefer_raster_effects)); -} - -EffectsRD *RendererStorageRD::get_effects() { - ERR_FAIL_NULL_V_MSG(effects, nullptr, "Effects haven't been initialised yet."); - return effects; -} - -void RendererStorageRD::capture_timestamps_begin() { - RD::get_singleton()->capture_timestamp("Frame Begin"); -} - -void RendererStorageRD::capture_timestamp(const String &p_name) { - RD::get_singleton()->capture_timestamp(p_name); -} - -uint32_t RendererStorageRD::get_captured_timestamps_count() const { - return RD::get_singleton()->get_captured_timestamps_count(); -} - -uint64_t RendererStorageRD::get_captured_timestamps_frame() const { - return RD::get_singleton()->get_captured_timestamps_frame(); -} - -uint64_t RendererStorageRD::get_captured_timestamp_gpu_time(uint32_t p_index) const { - return RD::get_singleton()->get_captured_timestamp_gpu_time(p_index); -} - -uint64_t RendererStorageRD::get_captured_timestamp_cpu_time(uint32_t p_index) const { - return RD::get_singleton()->get_captured_timestamp_cpu_time(p_index); -} - -String RendererStorageRD::get_captured_timestamp_name(uint32_t p_index) const { - return RD::get_singleton()->get_captured_timestamp_name(p_index); -} - -void RendererStorageRD::update_memory_info() { - texture_mem_cache = RenderingDevice::get_singleton()->get_memory_usage(RenderingDevice::MEMORY_TEXTURES); - buffer_mem_cache = RenderingDevice::get_singleton()->get_memory_usage(RenderingDevice::MEMORY_BUFFERS); - total_mem_cache = RenderingDevice::get_singleton()->get_memory_usage(RenderingDevice::MEMORY_TOTAL); -} -uint64_t RendererStorageRD::get_rendering_info(RS::RenderingInfo p_info) { - if (p_info == RS::RENDERING_INFO_TEXTURE_MEM_USED) { - return texture_mem_cache; - } else if (p_info == RS::RENDERING_INFO_BUFFER_MEM_USED) { - return buffer_mem_cache; - } else if (p_info == RS::RENDERING_INFO_VIDEO_MEM_USED) { - return total_mem_cache; - } - return 0; -} - -String RendererStorageRD::get_video_adapter_name() const { - return RenderingDevice::get_singleton()->get_device_name(); -} - -String RendererStorageRD::get_video_adapter_vendor() const { - return RenderingDevice::get_singleton()->get_device_vendor_name(); -} - -RenderingDevice::DeviceType RendererStorageRD::get_video_adapter_type() const { - return RenderingDevice::get_singleton()->get_device_type(); -} - -String RendererStorageRD::get_video_adapter_api_version() const { - return RenderingDevice::get_singleton()->get_device_api_version(); -} - -RendererStorageRD *RendererStorageRD::base_singleton = nullptr; - -RendererStorageRD::RendererStorageRD() { - base_singleton = this; -} - -RendererStorageRD::~RendererStorageRD() { - if (effects) { - memdelete(effects); - effects = nullptr; - } -} diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h deleted file mode 100644 index 07fae45a26..0000000000 --- a/servers/rendering/renderer_rd/renderer_storage_rd.h +++ /dev/null @@ -1,306 +0,0 @@ -/*************************************************************************/ -/* renderer_storage_rd.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef RENDERING_SERVER_STORAGE_RD_H -#define RENDERING_SERVER_STORAGE_RD_H - -#include "core/templates/list.h" -#include "core/templates/local_vector.h" -#include "core/templates/rid_owner.h" -#include "servers/rendering/renderer_compositor.h" -#include "servers/rendering/renderer_rd/effects_rd.h" -#include "servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl.gen.h" -#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" -#include "servers/rendering/renderer_scene_render.h" -#include "servers/rendering/rendering_device.h" -#include "servers/rendering/shader_compiler.h" - -class RendererStorageRD : public RendererStorage { -public: - static _FORCE_INLINE_ void store_transform(const Transform3D &p_mtx, float *p_array) { - p_array[0] = p_mtx.basis.rows[0][0]; - p_array[1] = p_mtx.basis.rows[1][0]; - p_array[2] = p_mtx.basis.rows[2][0]; - p_array[3] = 0; - p_array[4] = p_mtx.basis.rows[0][1]; - p_array[5] = p_mtx.basis.rows[1][1]; - p_array[6] = p_mtx.basis.rows[2][1]; - p_array[7] = 0; - p_array[8] = p_mtx.basis.rows[0][2]; - p_array[9] = p_mtx.basis.rows[1][2]; - p_array[10] = p_mtx.basis.rows[2][2]; - p_array[11] = 0; - p_array[12] = p_mtx.origin.x; - p_array[13] = p_mtx.origin.y; - p_array[14] = p_mtx.origin.z; - p_array[15] = 1; - } - - static _FORCE_INLINE_ void store_basis_3x4(const Basis &p_mtx, float *p_array) { - p_array[0] = p_mtx.rows[0][0]; - p_array[1] = p_mtx.rows[1][0]; - p_array[2] = p_mtx.rows[2][0]; - p_array[3] = 0; - p_array[4] = p_mtx.rows[0][1]; - p_array[5] = p_mtx.rows[1][1]; - p_array[6] = p_mtx.rows[2][1]; - p_array[7] = 0; - p_array[8] = p_mtx.rows[0][2]; - p_array[9] = p_mtx.rows[1][2]; - p_array[10] = p_mtx.rows[2][2]; - p_array[11] = 0; - } - - static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_mtx, float *p_array) { - p_array[0] = p_mtx.rows[0][0]; - p_array[1] = p_mtx.rows[1][0]; - p_array[2] = p_mtx.rows[2][0]; - p_array[3] = 0; - p_array[4] = p_mtx.rows[0][1]; - p_array[5] = p_mtx.rows[1][1]; - p_array[6] = p_mtx.rows[2][1]; - p_array[7] = 0; - p_array[8] = p_mtx.rows[0][2]; - p_array[9] = p_mtx.rows[1][2]; - p_array[10] = p_mtx.rows[2][2]; - p_array[11] = 0; - } - - static _FORCE_INLINE_ void store_transform_transposed_3x4(const Transform3D &p_mtx, float *p_array) { - p_array[0] = p_mtx.basis.rows[0][0]; - p_array[1] = p_mtx.basis.rows[0][1]; - p_array[2] = p_mtx.basis.rows[0][2]; - p_array[3] = p_mtx.origin.x; - p_array[4] = p_mtx.basis.rows[1][0]; - p_array[5] = p_mtx.basis.rows[1][1]; - p_array[6] = p_mtx.basis.rows[1][2]; - p_array[7] = p_mtx.origin.y; - p_array[8] = p_mtx.basis.rows[2][0]; - p_array[9] = p_mtx.basis.rows[2][1]; - p_array[10] = p_mtx.basis.rows[2][2]; - p_array[11] = p_mtx.origin.z; - } - - static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) { - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - p_array[i * 4 + j] = p_mtx.matrix[i][j]; - } - } - } - - static _FORCE_INLINE_ void store_soft_shadow_kernel(const float *p_kernel, float *p_array) { - for (int i = 0; i < 128; i++) { - p_array[i] = p_kernel[i]; - } - } - -private: - /* FOG VOLUMES */ - - struct FogVolume { - RID material; - Vector3 extents = Vector3(1, 1, 1); - - RS::FogVolumeShape shape = RS::FOG_VOLUME_SHAPE_BOX; - - Dependency dependency; - }; - - mutable RID_Owner<FogVolume, true> fog_volume_owner; - - /* visibility_notifier */ - - struct VisibilityNotifier { - AABB aabb; - Callable enter_callback; - Callable exit_callback; - Dependency dependency; - }; - - mutable RID_Owner<VisibilityNotifier> visibility_notifier_owner; - - /* VOXEL GI */ - - struct VoxelGI { - RID octree_buffer; - RID data_buffer; - RID sdf_texture; - - uint32_t octree_buffer_size = 0; - uint32_t data_buffer_size = 0; - - Vector<int> level_counts; - - int cell_count = 0; - - Transform3D to_cell_xform; - AABB bounds; - Vector3i octree_size; - - float dynamic_range = 2.0; - float energy = 1.0; - float bias = 1.4; - float normal_bias = 0.0; - float propagation = 0.7; - bool interior = false; - bool use_two_bounces = false; - - float anisotropy_strength = 0.5; - - uint32_t version = 1; - uint32_t data_version = 1; - - Dependency dependency; - }; - - mutable RID_Owner<VoxelGI, true> voxel_gi_owner; - - /* EFFECTS */ - - EffectsRD *effects = nullptr; - -public: - //internal usage - - void base_update_dependency(RID p_base, DependencyTracker *p_instance); - - /* VOXEL GI API */ - - RID voxel_gi_allocate(); - void voxel_gi_initialize(RID p_voxel_gi); - - void voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts); - - AABB voxel_gi_get_bounds(RID p_voxel_gi) const; - Vector3i voxel_gi_get_octree_size(RID p_voxel_gi) const; - Vector<uint8_t> voxel_gi_get_octree_cells(RID p_voxel_gi) const; - Vector<uint8_t> voxel_gi_get_data_cells(RID p_voxel_gi) const; - Vector<uint8_t> voxel_gi_get_distance_field(RID p_voxel_gi) const; - - Vector<int> voxel_gi_get_level_counts(RID p_voxel_gi) const; - Transform3D voxel_gi_get_to_cell_xform(RID p_voxel_gi) const; - - void voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range); - float voxel_gi_get_dynamic_range(RID p_voxel_gi) const; - - void voxel_gi_set_propagation(RID p_voxel_gi, float p_range); - float voxel_gi_get_propagation(RID p_voxel_gi) const; - - void voxel_gi_set_energy(RID p_voxel_gi, float p_energy); - float voxel_gi_get_energy(RID p_voxel_gi) const; - - void voxel_gi_set_bias(RID p_voxel_gi, float p_bias); - float voxel_gi_get_bias(RID p_voxel_gi) const; - - void voxel_gi_set_normal_bias(RID p_voxel_gi, float p_range); - float voxel_gi_get_normal_bias(RID p_voxel_gi) const; - - void voxel_gi_set_interior(RID p_voxel_gi, bool p_enable); - bool voxel_gi_is_interior(RID p_voxel_gi) const; - - void voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable); - bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const; - - void voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength); - float voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const; - - uint32_t voxel_gi_get_version(RID p_probe); - uint32_t voxel_gi_get_data_version(RID p_probe); - - RID voxel_gi_get_octree_buffer(RID p_voxel_gi) const; - RID voxel_gi_get_data_buffer(RID p_voxel_gi) const; - - RID voxel_gi_get_sdf_texture(RID p_voxel_gi); - - /* FOG VOLUMES */ - - virtual RID fog_volume_allocate(); - virtual void fog_volume_initialize(RID p_rid); - - virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape); - virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents); - virtual void fog_volume_set_material(RID p_fog_volume, RID p_material); - virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const; - virtual RID fog_volume_get_material(RID p_fog_volume) const; - virtual AABB fog_volume_get_aabb(RID p_fog_volume) const; - virtual Vector3 fog_volume_get_extents(RID p_fog_volume) const; - - /* VISIBILITY NOTIFIER */ - - virtual RID visibility_notifier_allocate(); - virtual void visibility_notifier_initialize(RID p_notifier); - virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb); - virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable); - - virtual AABB visibility_notifier_get_aabb(RID p_notifier) const; - virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred); - - RS::InstanceType get_base_type(RID p_rid) const; - - bool free(RID p_rid); - - bool has_os_feature(const String &p_feature) const; - - void update_dirty_resources(); - - void set_debug_generate_wireframes(bool p_generate) {} - - //keep cached since it can be called form any thread - uint64_t texture_mem_cache = 0; - uint64_t buffer_mem_cache = 0; - uint64_t total_mem_cache = 0; - - virtual void update_memory_info(); - virtual uint64_t get_rendering_info(RS::RenderingInfo p_info); - - String get_video_adapter_name() const; - String get_video_adapter_vendor() const; - RenderingDevice::DeviceType get_video_adapter_type() const; - String get_video_adapter_api_version() const; - - virtual void capture_timestamps_begin(); - virtual void capture_timestamp(const String &p_name); - virtual uint32_t get_captured_timestamps_count() const; - virtual uint64_t get_captured_timestamps_frame() const; - virtual uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const; - virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const; - virtual String get_captured_timestamp_name(uint32_t p_index) const; - - static RendererStorageRD *base_singleton; - - void init_effects(bool p_prefer_raster_effects); - EffectsRD *get_effects(); - - RendererStorageRD(); - ~RendererStorageRD(); -}; - -#endif // RASTERIZER_STORAGE_RD_H diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp index fdfecf2d2c..04e05380f1 100644 --- a/servers/rendering/renderer_rd/shader_rd.cpp +++ b/servers/rendering/renderer_rd/shader_rd.cpp @@ -522,7 +522,7 @@ void ShaderRD::_compile_version(Version *p_version) { p_version->valid = true; } -void ShaderRD::version_set_code(RID p_version, const Map<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines) { +void ShaderRD::version_set_code(RID p_version, const HashMap<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines) { ERR_FAIL_COND(is_compute); Version *version = version_owner.get_or_null(p_version); @@ -547,7 +547,7 @@ void ShaderRD::version_set_code(RID p_version, const Map<String, String> &p_code } } -void ShaderRD::version_set_compute_code(RID p_version, const Map<String, String> &p_code, const String &p_uniforms, const String &p_compute_globals, const Vector<String> &p_custom_defines) { +void ShaderRD::version_set_compute_code(RID p_version, const HashMap<String, String> &p_code, const String &p_uniforms, const String &p_compute_globals, const Vector<String> &p_custom_defines) { ERR_FAIL_COND(!is_compute); Version *version = version_owner.get_or_null(p_version); diff --git a/servers/rendering/renderer_rd/shader_rd.h b/servers/rendering/renderer_rd/shader_rd.h index 8e57f0d9af..40b10808c2 100644 --- a/servers/rendering/renderer_rd/shader_rd.h +++ b/servers/rendering/renderer_rd/shader_rd.h @@ -35,7 +35,7 @@ #include "core/string/string_builder.h" #include "core/templates/hash_map.h" #include "core/templates/local_vector.h" -#include "core/templates/map.h" +#include "core/templates/rb_map.h" #include "core/templates/rid_owner.h" #include "core/variant/variant.h" #include "servers/rendering_server.h" @@ -51,7 +51,7 @@ class ShaderRD { CharString vertex_globals; CharString compute_globals; CharString fragment_globals; - Map<StringName, CharString> code_sections; + HashMap<StringName, CharString> code_sections; Vector<CharString> custom_defines; Vector<uint8_t> *variant_data = nullptr; @@ -129,8 +129,8 @@ protected: public: RID version_create(); - void version_set_code(RID p_version, const Map<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines); - void version_set_compute_code(RID p_version, const Map<String, String> &p_code, const String &p_uniforms, const String &p_compute_globals, const Vector<String> &p_custom_defines); + void version_set_code(RID p_version, const HashMap<String, String> &p_code, const String &p_uniforms, const String &p_vertex_globals, const String &p_fragment_globals, const Vector<String> &p_custom_defines); + void version_set_compute_code(RID p_version, const HashMap<String, String> &p_code, const String &p_uniforms, const String &p_compute_globals, const Vector<String> &p_custom_defines); _FORCE_INLINE_ RID version_get_shader(RID p_version, int p_variant) { ERR_FAIL_INDEX_V(p_variant, variant_defines.size(), RID()); diff --git a/servers/rendering/renderer_rd/shaders/SCsub b/servers/rendering/renderer_rd/shaders/SCsub index acb843bfb6..d352743908 100644 --- a/servers/rendering/renderer_rd/shaders/SCsub +++ b/servers/rendering/renderer_rd/shaders/SCsub @@ -10,10 +10,11 @@ if "RD_GLSL" in env["BUILDERS"]: glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files] # make sure we recompile shaders if include files change - env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files) + env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files + ["#glsl_builders.py"]) # compile shaders for glsl_file in glsl_files: env.RD_GLSL(glsl_file) SConscript("effects/SCsub") +SConscript("environment/SCsub") diff --git a/servers/rendering/renderer_rd/shaders/effects/SCsub b/servers/rendering/renderer_rd/shaders/effects/SCsub index fc513d3fb9..741da8fe69 100644 --- a/servers/rendering/renderer_rd/shaders/effects/SCsub +++ b/servers/rendering/renderer_rd/shaders/effects/SCsub @@ -10,7 +10,7 @@ if "RD_GLSL" in env["BUILDERS"]: glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files] # make sure we recompile shaders if include files change - env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files) + env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files + ["#glsl_builders.py"]) # compile shaders for glsl_file in glsl_files: diff --git a/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl index 9787c9879d..1c17eabb56 100644 --- a/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl @@ -88,7 +88,7 @@ layout(set = 0, binding = 0) uniform sampler2DArray source_color; layout(set = 1, binding = 0) uniform sampler2DArray source_depth; layout(location = 1) out float depth; #endif /* MODE_TWO_SOURCES */ -#else +#else /* MULTIVIEW */ layout(set = 0, binding = 0) uniform sampler2D source_color; #ifdef MODE_TWO_SOURCES layout(set = 1, binding = 0) uniform sampler2D source_color2; @@ -139,7 +139,7 @@ void main() { //uv.y = 1.0 - uv.y; uv = 1.0 - uv; } -#endif +#endif /* MODE_PANORAMA_TO_DP */ #ifdef MULTIVIEW vec4 color = textureLod(source_color, uv, 0.0); @@ -148,12 +148,13 @@ void main() { depth = textureLod(source_depth, uv, 0.0).r; #endif /* MODE_TWO_SOURCES */ -#else +#else /* MULTIVIEW */ vec4 color = textureLod(source_color, uv, 0.0); #ifdef MODE_TWO_SOURCES color += textureLod(source_color2, uv, 0.0); #endif /* MODE_TWO_SOURCES */ #endif /* MULTIVIEW */ + if (params.force_luminance) { color.rgb = vec3(max(max(color.r, color.g), color.b)); } @@ -163,5 +164,6 @@ void main() { if (params.srgb) { color.rgb = linear_to_srgb(color.rgb); } + frag_color = color; } diff --git a/servers/rendering/renderer_rd/shaders/cube_to_dp.glsl b/servers/rendering/renderer_rd/shaders/effects/cube_to_dp.glsl index e77d0de719..e77d0de719 100644 --- a/servers/rendering/renderer_rd/shaders/cube_to_dp.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/cube_to_dp.glsl diff --git a/servers/rendering/renderer_rd/shaders/cubemap_downsampler.glsl b/servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler.glsl index 63f0ce690e..63f0ce690e 100644 --- a/servers/rendering/renderer_rd/shaders/cubemap_downsampler.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler.glsl diff --git a/servers/rendering/renderer_rd/shaders/cubemap_downsampler_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler_inc.glsl index 641e0906f5..641e0906f5 100644 --- a/servers/rendering/renderer_rd/shaders/cubemap_downsampler_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler_inc.glsl diff --git a/servers/rendering/renderer_rd/shaders/cubemap_downsampler_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler_raster.glsl index 0828ffd921..0828ffd921 100644 --- a/servers/rendering/renderer_rd/shaders/cubemap_downsampler_raster.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler_raster.glsl diff --git a/servers/rendering/renderer_rd/shaders/cubemap_filter.glsl b/servers/rendering/renderer_rd/shaders/effects/cubemap_filter.glsl index 2a774b0eb4..2a774b0eb4 100644 --- a/servers/rendering/renderer_rd/shaders/cubemap_filter.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/cubemap_filter.glsl diff --git a/servers/rendering/renderer_rd/shaders/cubemap_filter_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/cubemap_filter_raster.glsl index 0990dc7c2f..0990dc7c2f 100644 --- a/servers/rendering/renderer_rd/shaders/cubemap_filter_raster.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/cubemap_filter_raster.glsl diff --git a/servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl b/servers/rendering/renderer_rd/shaders/effects/cubemap_roughness.glsl index 1d46f59408..1d46f59408 100644 --- a/servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/cubemap_roughness.glsl diff --git a/servers/rendering/renderer_rd/shaders/cubemap_roughness_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_inc.glsl index 1bee428a6f..1bee428a6f 100644 --- a/servers/rendering/renderer_rd/shaders/cubemap_roughness_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_inc.glsl diff --git a/servers/rendering/renderer_rd/shaders/cubemap_roughness_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_raster.glsl index c29accd8a7..c29accd8a7 100644 --- a/servers/rendering/renderer_rd/shaders/cubemap_roughness_raster.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_raster.glsl diff --git a/servers/rendering/renderer_rd/shaders/resolve.glsl b/servers/rendering/renderer_rd/shaders/effects/resolve.glsl index 0e086331c0..0e086331c0 100644 --- a/servers/rendering/renderer_rd/shaders/resolve.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/resolve.glsl diff --git a/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl b/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl index 5a238452c0..62a7b0e7d7 100644 --- a/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl +++ b/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl @@ -426,12 +426,13 @@ vec3 screen_space_dither(vec2 frag_coord) { void main() { #ifdef SUBPASS // SUBPASS and MULTIVIEW can be combined but in that case we're already reading from the correct layer - vec3 color = subpassLoad(input_color).rgb * params.luminance_multiplier; + vec4 color = subpassLoad(input_color); #elif defined(MULTIVIEW) - vec3 color = textureLod(source_color, vec3(uv_interp, ViewIndex), 0.0f).rgb * params.luminance_multiplier; + vec4 color = textureLod(source_color, vec3(uv_interp, ViewIndex), 0.0f); #else - vec3 color = textureLod(source_color, uv_interp, 0.0f).rgb * params.luminance_multiplier; + vec4 color = textureLod(source_color, uv_interp, 0.0f); #endif + color.rgb *= params.luminance_multiplier; // Exposure @@ -443,10 +444,15 @@ void main() { } #endif - color *= exposure; + color.rgb *= exposure; // Early Tonemap & SRGB Conversion #ifndef SUBPASS + if (params.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) { vec3 glow = gather_glow(source_glow, uv_interp) * params.luminance_multiplier; if (params.glow_map_strength > 0.001) { @@ -454,21 +460,17 @@ void main() { } color.rgb = mix(color.rgb, glow, params.glow_intensity); } - - if (params.use_fxaa) { - color = do_fxaa(color, exposure, uv_interp); - } #endif if (params.use_debanding) { // For best results, debanding should be done before tonemapping. // Otherwise, we're adding noise to an already-quantized image. - color += screen_space_dither(gl_FragCoord.xy); + color.rgb += screen_space_dither(gl_FragCoord.xy); } - color = apply_tonemapping(color, params.white); + color.rgb = apply_tonemapping(color.rgb, params.white); - color = linear_to_srgb(color); // regular linear -> SRGB conversion + color.rgb = linear_to_srgb(color.rgb); // regular linear -> SRGB conversion #ifndef SUBPASS // Glow @@ -482,19 +484,19 @@ void main() { glow = apply_tonemapping(glow, params.white); glow = linear_to_srgb(glow); - color = apply_glow(color, glow); + color.rgb = apply_glow(color.rgb, glow); } #endif // Additional effects if (params.use_bcs) { - color = apply_bcs(color, params.bcs); + color.rgb = apply_bcs(color.rgb, params.bcs); } if (params.use_color_correction) { - color = apply_color_correction(color); + color.rgb = apply_color_correction(color.rgb); } - frag_color = vec4(color, 1.0f); + frag_color = color; } diff --git a/servers/rendering/renderer_rd/shaders/effects/vrs.glsl b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl new file mode 100644 index 0000000000..5ef83c0b44 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl @@ -0,0 +1,72 @@ +#[vertex] + +#version 450 + +#VERSION_DEFINES + +#ifdef MULTIVIEW +#ifdef has_VK_KHR_multiview +#extension GL_EXT_multiview : enable +#define ViewIndex gl_ViewIndex +#else // has_VK_KHR_multiview +#define ViewIndex 0 +#endif // has_VK_KHR_multiview +#endif //MULTIVIEW + +#ifdef MULTIVIEW +layout(location = 0) out vec3 uv_interp; +#else +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]; +#ifdef MULTIVIEW + uv_interp.z = ViewIndex; +#endif + + gl_Position = vec4(uv_interp.xy * 2.0 - 1.0, 0.0, 1.0); +} + +#[fragment] + +#version 450 + +#VERSION_DEFINES + +#ifdef MULTIVIEW +#ifdef has_VK_KHR_multiview +#extension GL_EXT_multiview : enable +#define ViewIndex gl_ViewIndex +#else // has_VK_KHR_multiview +#define ViewIndex 0 +#endif // has_VK_KHR_multiview +#endif //MULTIVIEW + +#ifdef MULTIVIEW +layout(location = 0) in vec3 uv_interp; +layout(set = 0, binding = 0) uniform sampler2DArray source_color; +#else /* MULTIVIEW */ +layout(location = 0) in vec2 uv_interp; +layout(set = 0, binding = 0) uniform sampler2D source_color; +#endif /* MULTIVIEW */ + +layout(location = 0) out uint frag_color; + +void main() { +#ifdef MULTIVIEW + vec3 uv = uv_interp; +#else + vec2 uv = uv_interp; +#endif + +#ifdef MULTIVIEW + vec4 color = textureLod(source_color, uv, 0.0); +#else /* MULTIVIEW */ + vec4 color = textureLod(source_color, uv, 0.0); +#endif /* MULTIVIEW */ + + // See if we can change the sampler to one that returns int... + frag_color = uint(color.r * 256.0); +} diff --git a/servers/rendering/renderer_rd/shaders/environment/SCsub b/servers/rendering/renderer_rd/shaders/environment/SCsub new file mode 100644 index 0000000000..741da8fe69 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/environment/SCsub @@ -0,0 +1,17 @@ +#!/usr/bin/env python + +Import("env") + +if "RD_GLSL" in env["BUILDERS"]: + # find all include files + gl_include_files = [str(f) for f in Glob("*_inc.glsl")] + + # find all shader code(all glsl files excluding our include files) + glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files] + + # make sure we recompile shaders if include files change + env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files + ["#glsl_builders.py"]) + + # compile shaders + for glsl_file in glsl_files: + env.RD_GLSL(glsl_file) diff --git a/servers/rendering/renderer_rd/shaders/gi.glsl b/servers/rendering/renderer_rd/shaders/environment/gi.glsl index 0c7f08813b..5f34e7112d 100644 --- a/servers/rendering/renderer_rd/shaders/gi.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/gi.glsl @@ -8,6 +8,12 @@ layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; #define M_PI 3.141592 +/* Specialization Constants (Toggles) */ + +layout(constant_id = 0) const bool sc_half_res = false; +layout(constant_id = 1) const bool sc_use_full_projection_matrix = false; +layout(constant_id = 2) const bool sc_use_vrs = false; + #define SDFGI_MAX_CASCADES 8 //set 0 for SDFGI and render buffers @@ -86,19 +92,31 @@ voxel_gi_instances; layout(set = 0, binding = 17) uniform texture3D voxel_gi_textures[MAX_VOXEL_GI_INSTANCES]; -layout(push_constant, std430) uniform Params { +layout(set = 0, binding = 18, std140) uniform SceneData { + mat4x4 inv_projection[2]; + mat4x4 cam_transform; + vec4 eye_offset[2]; + ivec2 screen_size; - float z_near; - float z_far; + float pad1; + float pad2; +} +scene_data; - vec4 proj_info; +layout(r8ui, set = 0, binding = 19) uniform restrict readonly uimage2D vrs_buffer; +layout(push_constant, std430) uniform Params { uint max_voxel_gi_instances; bool high_quality_vct; bool orthogonal; - uint pad; + uint view_index; + + vec4 proj_info; - mat3x4 cam_rotation; + float z_near; + float z_far; + float pad2; + float pad3; } params; @@ -130,23 +148,34 @@ vec4 blend_color(vec4 src, vec4 dst) { } vec3 reconstruct_position(ivec2 screen_pos) { - vec3 pos; - pos.z = texelFetch(sampler2D(depth_buffer, linear_sampler), screen_pos, 0).r; + if (sc_use_full_projection_matrix) { + vec4 pos; + pos.xy = (2.0 * vec2(screen_pos) / vec2(scene_data.screen_size)) - 1.0; + pos.z = texelFetch(sampler2D(depth_buffer, linear_sampler), screen_pos, 0).r * 2.0 - 1.0; + pos.w = 1.0; + + pos = scene_data.inv_projection[params.view_index] * pos; - pos.z = pos.z * 2.0 - 1.0; - if (params.orthogonal) { - pos.z = ((pos.z + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; + return pos.xyz / pos.w; } else { - pos.z = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - pos.z * (params.z_far - params.z_near)); - } - pos.z = -pos.z; + vec3 pos; + pos.z = texelFetch(sampler2D(depth_buffer, linear_sampler), screen_pos, 0).r; + + pos.z = pos.z * 2.0 - 1.0; + if (params.orthogonal) { + pos.z = ((pos.z + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; + } else { + pos.z = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - pos.z * (params.z_far - params.z_near)); + } + pos.z = -pos.z; - pos.xy = vec2(screen_pos) * params.proj_info.xy + params.proj_info.zw; - if (!params.orthogonal) { - pos.xy *= pos.z; - } + pos.xy = vec2(screen_pos) * params.proj_info.xy + params.proj_info.zw; + if (!params.orthogonal) { + pos.xy *= pos.z; + } - return pos; + return pos; + } } void sdfvoxel_gi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_normal, vec3 cam_specular_normal, float roughness, out vec3 diffuse_light, out vec3 specular_light) { @@ -566,7 +595,6 @@ void voxel_gi_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 vec4 fetch_normal_and_roughness(ivec2 pos) { vec4 normal_roughness = texelFetch(sampler2D(normal_roughness_buffer, linear_sampler), pos, 0); - normal_roughness.xyz = normalize(normal_roughness.xyz * 2.0 - 1.0); return normal_roughness; } @@ -579,9 +607,10 @@ void process_gi(ivec2 pos, vec3 vertex, inout vec4 ambient_light, inout vec4 ref if (normal.length() > 0.5) { //valid normal, can do GI float roughness = normal_roughness.w; - vertex = mat3(params.cam_rotation) * vertex; - normal = normalize(mat3(params.cam_rotation) * normal); - vec3 reflection = normalize(reflect(normalize(vertex), normal)); + vec3 view = -normalize(mat3(scene_data.cam_transform) * (vertex - scene_data.eye_offset[gl_GlobalInvocationID.z].xyz)); + vertex = mat3(scene_data.cam_transform) * vertex; + normal = normalize(mat3(scene_data.cam_transform) * normal); + vec3 reflection = normalize(reflect(-view, normal)); #ifdef USE_SDFGI sdfgi_process(vertex, normal, reflection, roughness, ambient_light, reflection_light); @@ -626,10 +655,36 @@ void process_gi(ivec2 pos, vec3 vertex, inout vec4 ambient_light, inout vec4 ref void main() { ivec2 pos = ivec2(gl_GlobalInvocationID.xy); -#ifdef MODE_HALF_RES - pos <<= 1; -#endif - if (any(greaterThanEqual(pos, params.screen_size))) { //too large, do nothing + uint vrs_x, vrs_y; + if (sc_use_vrs) { + ivec2 vrs_pos; + + // Currenty we use a 16x16 texel, possibly some day make this configurable. + if (sc_half_res) { + vrs_pos = pos >> 3; + } else { + vrs_pos = pos >> 4; + } + + uint vrs_texel = imageLoad(vrs_buffer, vrs_pos).r; + // note, valid values for vrs_x and vrs_y are 1, 2 and 4. + vrs_x = 1 << ((vrs_texel >> 2) & 3); + vrs_y = 1 << (vrs_texel & 3); + + if (mod(pos.x, vrs_x) != 0) { + return; + } + + if (mod(pos.y, vrs_y) != 0) { + return; + } + } + + if (sc_half_res) { + pos <<= 1; + } + + if (any(greaterThanEqual(pos, scene_data.screen_size))) { //too large, do nothing return; } @@ -641,10 +696,69 @@ void main() { process_gi(pos, vertex, ambient_light, reflection_light); -#ifdef MODE_HALF_RES - pos >>= 1; -#endif + if (sc_half_res) { + pos >>= 1; + } imageStore(ambient_buffer, pos, ambient_light); imageStore(reflection_buffer, pos, reflection_light); + + if (sc_use_vrs) { + if (vrs_x > 1) { + imageStore(ambient_buffer, pos + ivec2(1, 0), ambient_light); + imageStore(reflection_buffer, pos + ivec2(1, 0), reflection_light); + } + + if (vrs_x > 2) { + imageStore(ambient_buffer, pos + ivec2(2, 0), ambient_light); + imageStore(reflection_buffer, pos + ivec2(2, 0), reflection_light); + + imageStore(ambient_buffer, pos + ivec2(3, 0), ambient_light); + imageStore(reflection_buffer, pos + ivec2(3, 0), reflection_light); + } + + if (vrs_y > 1) { + imageStore(ambient_buffer, pos + ivec2(0, 1), ambient_light); + imageStore(reflection_buffer, pos + ivec2(0, 1), reflection_light); + } + + if (vrs_y > 1 && vrs_x > 1) { + imageStore(ambient_buffer, pos + ivec2(1, 1), ambient_light); + imageStore(reflection_buffer, pos + ivec2(1, 1), reflection_light); + } + + if (vrs_y > 1 && vrs_x > 2) { + imageStore(ambient_buffer, pos + ivec2(2, 1), ambient_light); + imageStore(reflection_buffer, pos + ivec2(2, 1), reflection_light); + + imageStore(ambient_buffer, pos + ivec2(3, 1), ambient_light); + imageStore(reflection_buffer, pos + ivec2(3, 1), reflection_light); + } + + if (vrs_y > 2) { + imageStore(ambient_buffer, pos + ivec2(0, 2), ambient_light); + imageStore(reflection_buffer, pos + ivec2(0, 2), reflection_light); + imageStore(ambient_buffer, pos + ivec2(0, 3), ambient_light); + imageStore(reflection_buffer, pos + ivec2(0, 3), reflection_light); + } + + if (vrs_y > 2 && vrs_x > 1) { + imageStore(ambient_buffer, pos + ivec2(1, 2), ambient_light); + imageStore(reflection_buffer, pos + ivec2(1, 2), reflection_light); + imageStore(ambient_buffer, pos + ivec2(1, 3), ambient_light); + imageStore(reflection_buffer, pos + ivec2(1, 3), reflection_light); + } + + if (vrs_y > 2 && vrs_x > 2) { + imageStore(ambient_buffer, pos + ivec2(2, 2), ambient_light); + imageStore(reflection_buffer, pos + ivec2(2, 2), reflection_light); + imageStore(ambient_buffer, pos + ivec2(2, 3), ambient_light); + imageStore(reflection_buffer, pos + ivec2(2, 3), reflection_light); + + imageStore(ambient_buffer, pos + ivec2(3, 2), ambient_light); + imageStore(reflection_buffer, pos + ivec2(3, 2), reflection_light); + imageStore(ambient_buffer, pos + ivec2(3, 3), ambient_light); + imageStore(reflection_buffer, pos + ivec2(3, 3), reflection_light); + } + } } diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_debug.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl index 802a410825..af5f7d0a58 100644 --- a/servers/rendering/renderer_rd/shaders/sdfgi_debug.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl @@ -40,10 +40,13 @@ layout(push_constant, std430) uniform Params { bool use_occlusion; float y_mult; - vec3 cam_extent; int probe_axis_size; + float z_near; + float reserved1; + float reserved2; mat4 cam_transform; + mat4 inv_projection; } params; @@ -81,8 +84,9 @@ void main() { { ray_pos = params.cam_transform[3].xyz; - ray_dir.xy = params.cam_extent.xy * ((vec2(screen_pos) / vec2(params.screen_size)) * 2.0 - 1.0); - ray_dir.z = params.cam_extent.z; + ray_dir.xy = ((vec2(screen_pos) / vec2(params.screen_size)) * 2.0 - 1.0); + ray_dir.z = params.z_near; + ray_dir = (params.inv_projection * vec4(ray_dir, 1.0)).xyz; ray_dir = normalize(mat3(params.cam_transform) * ray_dir); } diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug_probes.glsl index e0be0bca12..75b1ad2130 100644 --- a/servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug_probes.glsl @@ -2,13 +2,28 @@ #version 450 +#if defined(USE_MULTIVIEW) && defined(has_VK_KHR_multiview) +#extension GL_EXT_multiview : enable +#endif + +#ifdef USE_MULTIVIEW +#ifdef has_VK_KHR_multiview +#define ViewIndex gl_ViewIndex +#else // has_VK_KHR_multiview +// !BAS! This needs to become an input once we implement our fallback! +#define ViewIndex 0 +#endif // has_VK_KHR_multiview +#else // USE_MULTIVIEW +// Set to zero, not supported in non stereo +#define ViewIndex 0 +#endif //USE_MULTIVIEW + #VERSION_DEFINES #define MAX_CASCADES 8 +#define MAX_VIEWS 2 layout(push_constant, std430) uniform Params { - mat4 projection; - uint band_power; uint sections_in_band; uint band_mask; @@ -68,6 +83,11 @@ cascades; layout(set = 0, binding = 4) uniform texture3D occlusion_texture; layout(set = 0, binding = 3) uniform sampler linear_sampler; +layout(set = 0, binding = 5, std140) uniform SceneData { + mat4 projection[MAX_VIEWS]; +} +scene_data; + void main() { #ifdef MODE_PROBES probe_index = gl_InstanceIndex; @@ -85,7 +105,7 @@ void main() { vertex += (cascades.data[params.cascade].offset + vec3(probe_cell) * probe_cell_size) / vec3(1.0, params.y_mult, 1.0); - gl_Position = params.projection * vec4(vertex, 1.0); + gl_Position = scene_data.projection[ViewIndex] * vec4(vertex, 1.0); #endif #ifdef MODE_VISIBILITY @@ -144,7 +164,7 @@ void main() { visibility = dot(texelFetch(sampler3D(occlusion_texture, linear_sampler), tex_pos, 0), layer_axis[occlusion_layer]); - gl_Position = params.projection * vec4(vertex, 1.0); + gl_Position = scene_data.projection[ViewIndex] * vec4(vertex, 1.0); #endif } @@ -153,16 +173,32 @@ void main() { #version 450 +#if defined(USE_MULTIVIEW) && defined(has_VK_KHR_multiview) +#extension GL_EXT_multiview : enable +#endif + +#ifdef USE_MULTIVIEW +#ifdef has_VK_KHR_multiview +#define ViewIndex gl_ViewIndex +#else // has_VK_KHR_multiview +// !BAS! This needs to become an input once we implement our fallback! +#define ViewIndex 0 +#endif // has_VK_KHR_multiview +#else // USE_MULTIVIEW +// Set to zero, not supported in non stereo +#define ViewIndex 0 +#endif //USE_MULTIVIEW + #VERSION_DEFINES +#define MAX_VIEWS 2 + layout(location = 0) out vec4 frag_color; layout(set = 0, binding = 2) uniform texture2DArray lightprobe_texture; layout(set = 0, binding = 3) uniform sampler linear_sampler; layout(push_constant, std430) uniform Params { - mat4 projection; - uint band_power; uint sections_in_band; uint band_mask; diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl index b95fad650e..b95fad650e 100644 --- a/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_integrate.glsl index 9c03297f5c..9c03297f5c 100644 --- a/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_integrate.glsl diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl index bce98f4054..bce98f4054 100644 --- a/servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl diff --git a/servers/rendering/renderer_rd/shaders/voxel_gi.glsl b/servers/rendering/renderer_rd/shaders/environment/voxel_gi.glsl index 577c6d0cd0..577c6d0cd0 100644 --- a/servers/rendering/renderer_rd/shaders/voxel_gi.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/voxel_gi.glsl diff --git a/servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl b/servers/rendering/renderer_rd/shaders/environment/voxel_gi_debug.glsl index fd7a2bf8ad..fd7a2bf8ad 100644 --- a/servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/voxel_gi_debug.glsl diff --git a/servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl b/servers/rendering/renderer_rd/shaders/environment/voxel_gi_sdf.glsl index 47a611a543..47a611a543 100644 --- a/servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl +++ b/servers/rendering/renderer_rd/shaders/environment/voxel_gi_sdf.glsl diff --git a/servers/rendering/renderer_rd/shaders/particles.glsl b/servers/rendering/renderer_rd/shaders/particles.glsl index 1b1051ecfa..acb62b812e 100644 --- a/servers/rendering/renderer_rd/shaders/particles.glsl +++ b/servers/rendering/renderer_rd/shaders/particles.glsl @@ -228,6 +228,14 @@ bool emit_subparticle(mat4 p_xform, vec3 p_velocity, vec4 p_color, vec4 p_custom return true; } +vec3 safe_normalize(vec3 direction) { + const float EPSILON = 0.001; + if (length(direction) < EPSILON) { + return vec3(0.0); + } + return normalize(direction); +} + #GLOBALS void main() { @@ -431,7 +439,7 @@ void main() { switch (FRAME.attractors[i].type) { case ATTRACTOR_TYPE_SPHERE: { - dir = normalize(rel_vec); + dir = safe_normalize(rel_vec); float d = length(local_pos) / FRAME.attractors[i].extents.x; if (d > 1.0) { continue; @@ -439,7 +447,7 @@ void main() { amount = max(0.0, 1.0 - d); } break; case ATTRACTOR_TYPE_BOX: { - dir = normalize(rel_vec); + dir = safe_normalize(rel_vec); vec3 abs_pos = abs(local_pos / FRAME.attractors[i].extents); float d = max(abs_pos.x, max(abs_pos.y, abs_pos.z)); @@ -455,13 +463,13 @@ void main() { continue; } vec3 s = texture(sampler3D(sdf_vec_textures[FRAME.attractors[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos).xyz; - dir = mat3(FRAME.attractors[i].transform) * normalize(s); //revert direction + dir = mat3(FRAME.attractors[i].transform) * safe_normalize(s); //revert direction amount = length(s); } break; } amount = pow(amount, FRAME.attractors[i].attenuation); - dir = normalize(mix(dir, FRAME.attractors[i].transform[2].xyz, FRAME.attractors[i].directionality)); + dir = safe_normalize(mix(dir, FRAME.attractors[i].transform[2].xyz, FRAME.attractors[i].directionality)); attractor_force -= amount * dir * FRAME.attractors[i].strength; } diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl index 58b4ded9f4..5947fc5351 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl @@ -83,6 +83,11 @@ layout(location = 5) out vec3 tangent_interp; layout(location = 6) out vec3 binormal_interp; #endif +#ifdef MOTION_VECTORS +layout(location = 7) out vec4 screen_position; +layout(location = 8) out vec4 prev_screen_position; +#endif + #ifdef MATERIAL_UNIFORMS_USED layout(set = MATERIAL_UNIFORM_SET, binding = 0, std140) uniform MaterialUniforms{ @@ -91,13 +96,15 @@ layout(set = MATERIAL_UNIFORM_SET, binding = 0, std140) uniform MaterialUniforms } material; #endif +float global_time; + #ifdef MODE_DUAL_PARABOLOID -layout(location = 8) out float dp_clip; +layout(location = 9) out float dp_clip; #endif -layout(location = 9) out flat uint instance_index_interp; +layout(location = 10) out flat uint instance_index_interp; #ifdef USE_MULTIVIEW #ifdef has_VK_KHR_multiview @@ -115,23 +122,12 @@ invariant gl_Position; #GLOBALS -void main() { +void vertex_shader(in uint instance_index, in bool is_multimesh, 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; #endif - uint instance_index = draw_call.instance_index; - - bool is_multimesh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH); - if (!is_multimesh) { - instance_index += gl_InstanceIndex; - } - - instance_index_interp = instance_index; - - mat4 model_matrix = instances.data[instance_index].transform; - mat3 model_normal_matrix; if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) { model_normal_matrix = transpose(inverse(mat3(model_matrix))); @@ -321,6 +317,11 @@ void main() { #endif vertex_interp = vertex; + +#ifdef MOTION_VECTORS + screen_pos = projection_matrix * vec4(vertex_interp, 1.0); +#endif + #ifdef NORMAL_USED normal_interp = normal; #endif @@ -375,6 +376,29 @@ void main() { #endif } +void main() { + uint instance_index = draw_call.instance_index; + + bool is_multimesh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH); + if (!is_multimesh) { + instance_index += gl_InstanceIndex; + } + + instance_index_interp = instance_index; + + mat4 model_matrix = instances.data[instance_index].transform; +#if defined(MOTION_VECTORS) + global_time = scene_data_block.prev_data.time; + vertex_shader(instance_index, is_multimesh, 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, scene_data_block.data, model_matrix, screen_position); +#else + global_time = scene_data_block.data.time; + vec4 screen_position; + vertex_shader(instance_index, is_multimesh, scene_data_block.data, model_matrix, screen_position); +#endif +} + #[fragment] #version 450 @@ -431,13 +455,18 @@ layout(location = 5) in vec3 tangent_interp; layout(location = 6) in vec3 binormal_interp; #endif +#ifdef MOTION_VECTORS +layout(location = 7) in vec4 screen_position; +layout(location = 8) in vec4 prev_screen_position; +#endif + #ifdef MODE_DUAL_PARABOLOID -layout(location = 8) in float dp_clip; +layout(location = 9) in float dp_clip; #endif -layout(location = 9) in flat uint instance_index_interp; +layout(location = 10) in flat uint instance_index_interp; #ifdef USE_MULTIVIEW #ifdef has_VK_KHR_multiview @@ -462,6 +491,8 @@ layout(location = 9) in flat uint instance_index_interp; #define inv_projection_matrix scene_data.inv_projection_matrix #endif +#define global_time scene_data_block.data.time + #if defined(ENABLE_SSS) && defined(ENABLE_TRANSMITTANCE) //both required for transmittance to be enabled #define LIGHT_TRANSMITTANCE_USED @@ -510,6 +541,10 @@ layout(location = 0) out vec4 frag_color; #endif // RENDER DEPTH +#ifdef MOTION_VECTORS +layout(location = 2) out vec2 motion_vector; +#endif + #include "scene_forward_aa_inc.glsl" #if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) @@ -528,24 +563,24 @@ layout(location = 0) out vec4 frag_color; #ifndef MODE_RENDER_DEPTH vec4 volumetric_fog_process(vec2 screen_uv, float z) { - vec3 fog_pos = vec3(screen_uv, z * scene_data.volumetric_fog_inv_length); + vec3 fog_pos = vec3(screen_uv, z * scene_data_block.data.volumetric_fog_inv_length); if (fog_pos.z < 0.0) { return vec4(0.0); } else if (fog_pos.z < 1.0) { - fog_pos.z = pow(fog_pos.z, scene_data.volumetric_fog_detail_spread); + fog_pos.z = pow(fog_pos.z, scene_data_block.data.volumetric_fog_detail_spread); } return texture(sampler3D(volumetric_fog_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), fog_pos); } vec4 fog_process(vec3 vertex) { - vec3 fog_color = scene_data.fog_light_color; + vec3 fog_color = scene_data_block.data.fog_light_color; - if (scene_data.fog_aerial_perspective > 0.0) { + if (scene_data_block.data.fog_aerial_perspective > 0.0) { vec3 sky_fog_color = vec3(0.0); - vec3 cube_view = scene_data.radiance_inverse_xform * vertex; + vec3 cube_view = scene_data_block.data.radiance_inverse_xform * vertex; // mip_level always reads from the second mipmap and higher so the fog is always slightly blurred - float mip_level = mix(1.0 / MAX_ROUGHNESS_LOD, 1.0, 1.0 - (abs(vertex.z) - scene_data.z_near) / (scene_data.z_far - scene_data.z_near)); + float mip_level = mix(1.0 / MAX_ROUGHNESS_LOD, 1.0, 1.0 - (abs(vertex.z) - scene_data_block.data.z_near) / (scene_data_block.data.z_far - scene_data_block.data.z_near)); #ifdef USE_RADIANCE_CUBEMAP_ARRAY float lod, blend; blend = modf(mip_level * MAX_ROUGHNESS_LOD, lod); @@ -554,29 +589,29 @@ vec4 fog_process(vec3 vertex) { #else sky_fog_color = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_view, mip_level * MAX_ROUGHNESS_LOD).rgb; #endif //USE_RADIANCE_CUBEMAP_ARRAY - fog_color = mix(fog_color, sky_fog_color, scene_data.fog_aerial_perspective); + fog_color = mix(fog_color, sky_fog_color, scene_data_block.data.fog_aerial_perspective); } - if (scene_data.fog_sun_scatter > 0.001) { + if (scene_data_block.data.fog_sun_scatter > 0.001) { vec4 sun_scatter = vec4(0.0); float sun_total = 0.0; vec3 view = normalize(vertex); - for (uint i = 0; i < scene_data.directional_light_count; i++) { + for (uint i = 0; i < scene_data_block.data.directional_light_count; i++) { vec3 light_color = directional_lights.data[i].color * directional_lights.data[i].energy; float light_amount = pow(max(dot(view, directional_lights.data[i].direction), 0.0), 8.0); - fog_color += light_color * light_amount * scene_data.fog_sun_scatter; + fog_color += light_color * light_amount * scene_data_block.data.fog_sun_scatter; } } - float fog_amount = 1.0 - exp(min(0.0, -length(vertex) * scene_data.fog_density)); + float fog_amount = 1.0 - exp(min(0.0, -length(vertex) * scene_data_block.data.fog_density)); - if (abs(scene_data.fog_height_density) >= 0.0001) { - float y = (scene_data.inv_view_matrix * vec4(vertex, 1.0)).y; + if (abs(scene_data_block.data.fog_height_density) >= 0.0001) { + float y = (scene_data_block.data.inv_view_matrix * vec4(vertex, 1.0)).y; - float y_dist = y - scene_data.fog_height; + float y_dist = y - scene_data_block.data.fog_height; - float vfog_amount = 1.0 - exp(min(0.0, y_dist * scene_data.fog_height_density)); + float vfog_amount = 1.0 - exp(min(0.0, y_dist * scene_data_block.data.fog_height_density)); fog_amount = max(vfog_amount, fog_amount); } @@ -601,18 +636,16 @@ uint cluster_get_range_clip_mask(uint i, uint z_min, uint z_max) { #endif //!MODE_RENDER DEPTH -void main() { -#ifdef MODE_DUAL_PARABOLOID - - if (dp_clip > 0.0) - discard; -#endif - +void fragment_shader(in SceneData scene_data) { uint instance_index = instance_index_interp; //lay out everything, whatever is unused is optimized away anyway vec3 vertex = vertex_interp; +#ifdef USE_MULTIVIEW + vec3 view = -normalize(vertex_interp - scene_data.eye_offset[ViewIndex].xyz); +#else vec3 view = -normalize(vertex_interp); +#endif vec3 albedo = vec3(1.0); vec3 backlight = vec3(0.0); vec4 transmittance_color = vec4(0.0, 0.0, 0.0, 1.0); @@ -679,7 +712,7 @@ void main() { float normal_map_depth = 1.0; - vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size + scene_data.screen_pixel_size * 0.5; //account for center + vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size; float sss_strength = 0.0; @@ -1169,7 +1202,7 @@ void main() { if (sc_use_forward_gi && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_VOXEL_GI)) { // process voxel_gi_instances uint index1 = instances.data[instance_index].gi_offset & 0xFFFF; - vec3 ref_vec = normalize(reflect(normalize(vertex), normal)); + vec3 ref_vec = normalize(reflect(-view, normal)); //find arbitrary tangent and bitangent, then build a matrix vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0); vec3 tangent = normalize(cross(v0, normal)); @@ -1205,12 +1238,20 @@ void main() { if (scene_data.gi_upscale_for_msaa) { vec2 base_coord = screen_uv; vec2 closest_coord = base_coord; +#ifdef USE_MULTIVIEW + float closest_ang = dot(normal, textureLod(sampler2DArray(normal_roughness_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), vec3(base_coord, ViewIndex), 0.0).xyz * 2.0 - 1.0); +#else // USE_MULTIVIEW float closest_ang = dot(normal, textureLod(sampler2D(normal_roughness_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), base_coord, 0.0).xyz * 2.0 - 1.0); +#endif // USE_MULTIVIEW for (int i = 0; i < 4; i++) { const vec2 neighbours[4] = vec2[](vec2(-1, 0), vec2(1, 0), vec2(0, -1), vec2(0, 1)); vec2 neighbour_coord = base_coord + neighbours[i] * scene_data.screen_pixel_size; +#ifdef USE_MULTIVIEW + float neighbour_ang = dot(normal, textureLod(sampler2DArray(normal_roughness_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), vec3(neighbour_coord, ViewIndex), 0.0).xyz * 2.0 - 1.0); +#else // USE_MULTIVIEW float neighbour_ang = dot(normal, textureLod(sampler2D(normal_roughness_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), neighbour_coord, 0.0).xyz * 2.0 - 1.0); +#endif // USE_MULTIVIEW if (neighbour_ang > closest_ang) { closest_ang = neighbour_ang; closest_coord = neighbour_coord; @@ -1223,8 +1264,13 @@ void main() { coord = screen_uv; } +#ifdef USE_MULTIVIEW + vec4 buffer_ambient = textureLod(sampler2DArray(ambient_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), vec3(coord, ViewIndex), 0.0); + vec4 buffer_reflection = textureLod(sampler2DArray(reflection_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), vec3(coord, ViewIndex), 0.0); +#else // USE_MULTIVIEW vec4 buffer_ambient = textureLod(sampler2D(ambient_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), coord, 0.0); vec4 buffer_reflection = textureLod(sampler2D(reflection_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), coord, 0.0); +#endif // USE_MULTIVIEW ambient_light = mix(ambient_light, buffer_ambient.rgb, buffer_ambient.a); specular_light = mix(specular_light, buffer_reflection.rgb, buffer_reflection.a); @@ -1287,7 +1333,7 @@ void main() { #else vec3 bent_normal = normal; #endif - reflection_process(reflection_index, vertex, bent_normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum); + reflection_process(reflection_index, view, vertex, bent_normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum); } } @@ -2015,4 +2061,23 @@ void main() { #endif //MODE_SEPARATE_SPECULAR #endif //MODE_RENDER_DEPTH +#ifdef MOTION_VECTORS + vec2 position_clip = (screen_position.xy / screen_position.w) - scene_data.taa_jitter; + vec2 prev_position_clip = (prev_screen_position.xy / prev_screen_position.w) - scene_data_block.prev_data.taa_jitter; + + vec2 position_uv = position_clip * vec2(0.5, 0.5); + vec2 prev_position_uv = prev_position_clip * vec2(0.5, 0.5); + + motion_vector = position_uv - prev_position_uv; +#endif +} + +void main() { +#ifdef MODE_DUAL_PARABOLOID + + if (dp_clip > 0.0) + discard; +#endif + + fragment_shader(scene_data_block.data); } diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl index f2672f10e7..0c23de96c3 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl @@ -171,7 +171,7 @@ sdfgi; /* Set 1: Render Pass (changes per render pass) */ -layout(set = 1, binding = 0, std140) uniform SceneData { +struct SceneData { mat4 projection_matrix; mat4 inv_projection_matrix; mat4 inv_view_matrix; @@ -180,6 +180,7 @@ layout(set = 1, binding = 0, std140) uniform SceneData { // only used for multiview mat4 projection_matrix_view[MAX_VIEWS]; mat4 inv_projection_matrix_view[MAX_VIEWS]; + vec4 eye_offset[MAX_VIEWS]; vec2 viewport_size; vec2 screen_pixel_size; @@ -249,11 +250,19 @@ layout(set = 1, binding = 0, std140) uniform SceneData { float reflection_multiplier; // one normally, zero when rendering reflections bool pancake_shadows; + vec2 taa_jitter; + uvec2 pad2; +}; + +layout(set = 1, binding = 0, std140) uniform SceneDataBlock { + SceneData data; + SceneData prev_data; } -scene_data; +scene_data_block; struct InstanceData { mat4 transform; + mat4 prev_transform; uint flags; uint instance_uniforms_ofs; //base offset in global buffer for instance variables uint gi_offset; //GI information when using lightmapping (VCT or lightmap index) @@ -308,10 +317,16 @@ layout(r32ui, set = 1, binding = 12) uniform restrict uimage3D geom_facing_grid; layout(set = 1, binding = 9) uniform texture2D depth_buffer; layout(set = 1, binding = 10) uniform texture2D color_buffer; +#ifdef USE_MULTIVIEW +layout(set = 1, binding = 11) uniform texture2DArray normal_roughness_buffer; +layout(set = 1, binding = 13) uniform texture2DArray ambient_buffer; +layout(set = 1, binding = 14) uniform texture2DArray reflection_buffer; +#else // USE_MULTIVIEW layout(set = 1, binding = 11) uniform texture2D normal_roughness_buffer; -layout(set = 1, binding = 12) uniform texture2D ao_buffer; layout(set = 1, binding = 13) uniform texture2D ambient_buffer; layout(set = 1, binding = 14) uniform texture2D reflection_buffer; +#endif +layout(set = 1, binding = 12) uniform texture2D ao_buffer; layout(set = 1, binding = 15) uniform texture2DArray sdfgi_lightprobe_texture; layout(set = 1, binding = 16) uniform texture3D sdfgi_occlusion_cascades; 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 bd1c2b5758..c92b29b14a 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl @@ -262,7 +262,7 @@ float sample_directional_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, ve float avg = 0.0; for (uint i = 0; i < sc_directional_soft_shadow_samples; i++) { - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + shadow_pixel_size * (disk_rotation * scene_data.directional_soft_shadow_kernel[i].xy), depth, 1.0)); + avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + shadow_pixel_size * (disk_rotation * scene_data_block.data.directional_soft_shadow_kernel[i].xy), depth, 1.0)); } return avg * (1.0 / float(sc_directional_soft_shadow_samples)); @@ -288,7 +288,7 @@ float sample_pcf_shadow(texture2D shadow, vec2 shadow_pixel_size, vec3 coord) { float avg = 0.0; for (uint i = 0; i < sc_soft_shadow_samples; i++) { - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + shadow_pixel_size * (disk_rotation * scene_data.soft_shadow_kernel[i].xy), depth, 1.0)); + avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + shadow_pixel_size * (disk_rotation * scene_data_block.data.soft_shadow_kernel[i].xy), depth, 1.0)); } return avg * (1.0 / float(sc_soft_shadow_samples)); @@ -311,10 +311,10 @@ float sample_omni_pcf_shadow(texture2D shadow, float blur_scale, vec2 coord, vec } float avg = 0.0; - vec2 offset_scale = blur_scale * 2.0 * scene_data.shadow_atlas_pixel_size / uv_rect.zw; + vec2 offset_scale = blur_scale * 2.0 * scene_data_block.data.shadow_atlas_pixel_size / uv_rect.zw; for (uint i = 0; i < sc_soft_shadow_samples; i++) { - vec2 offset = offset_scale * (disk_rotation * scene_data.soft_shadow_kernel[i].xy); + vec2 offset = offset_scale * (disk_rotation * scene_data_block.data.soft_shadow_kernel[i].xy); vec2 sample_coord = coord + offset; float sample_coord_length_sqaured = dot(sample_coord, sample_coord); @@ -351,7 +351,7 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex } for (uint i = 0; i < sc_directional_penumbra_shadow_samples; i++) { - vec2 suv = pssm_coord.xy + (disk_rotation * scene_data.directional_penumbra_shadow_kernel[i].xy) * tex_scale; + vec2 suv = pssm_coord.xy + (disk_rotation * scene_data_block.data.directional_penumbra_shadow_kernel[i].xy) * tex_scale; float d = textureLod(sampler2D(shadow, material_samplers[SAMPLER_LINEAR_CLAMP]), suv, 0.0).r; if (d < pssm_coord.z) { blocker_average += d; @@ -367,7 +367,7 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex float s = 0.0; for (uint i = 0; i < sc_directional_penumbra_shadow_samples; i++) { - vec2 suv = pssm_coord.xy + (disk_rotation * scene_data.directional_penumbra_shadow_kernel[i].xy) * tex_scale; + vec2 suv = pssm_coord.xy + (disk_rotation * scene_data_block.data.directional_penumbra_shadow_kernel[i].xy) * tex_scale; s += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(suv, pssm_coord.z, 1.0)); } @@ -394,7 +394,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) { #ifndef SHADOWS_DISABLED if (omni_lights.data[idx].shadow_enabled) { // there is a shadowmap - vec2 texel_size = scene_data.shadow_atlas_pixel_size; + vec2 texel_size = scene_data_block.data.shadow_atlas_pixel_size; vec4 base_uv_rect = omni_lights.data[idx].atlas_rect; base_uv_rect.xy += texel_size; base_uv_rect.zw -= texel_size * 2.0; @@ -438,7 +438,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) { bitangent *= omni_lights.data[idx].soft_shadow_size * omni_lights.data[idx].soft_shadow_scale; for (uint i = 0; i < sc_penumbra_shadow_samples; i++) { - vec2 disk = disk_rotation * scene_data.penumbra_shadow_kernel[i].xy; + vec2 disk = disk_rotation * scene_data_block.data.penumbra_shadow_kernel[i].xy; vec3 pos = local_vert + tangent * disk.x + bitangent * disk.y; @@ -474,7 +474,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) { shadow = 0.0; for (uint i = 0; i < sc_penumbra_shadow_samples; i++) { - vec2 disk = disk_rotation * scene_data.penumbra_shadow_kernel[i].xy; + vec2 disk = disk_rotation * scene_data_block.data.penumbra_shadow_kernel[i].xy; vec3 pos = local_vert + tangent * disk.x + bitangent * disk.y; pos = normalize(pos); @@ -579,7 +579,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v splane.xy = splane.xy * 0.5 + 0.5; splane.z = shadow_len * omni_lights.data[idx].inv_radius; splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw; - // splane.xy = clamp(splane.xy,clamp_rect.xy + scene_data.shadow_atlas_pixel_size,clamp_rect.xy + clamp_rect.zw - scene_data.shadow_atlas_pixel_size ); + // splane.xy = clamp(splane.xy,clamp_rect.xy + scene_data_block.data.shadow_atlas_pixel_size,clamp_rect.xy + clamp_rect.zw - scene_data_block.data.shadow_atlas_pixel_size ); splane.w = 1.0; //needed? i think it should be 1 already float shadow_z = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), splane.xy, 0.0).r; @@ -709,7 +709,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) { float uv_size = spot_lights.data[idx].soft_shadow_size * z_norm * spot_lights.data[idx].soft_shadow_scale; vec2 clamp_max = spot_lights.data[idx].atlas_rect.xy + spot_lights.data[idx].atlas_rect.zw; for (uint i = 0; i < sc_penumbra_shadow_samples; i++) { - vec2 suv = shadow_uv + (disk_rotation * scene_data.penumbra_shadow_kernel[i].xy) * uv_size; + vec2 suv = shadow_uv + (disk_rotation * scene_data_block.data.penumbra_shadow_kernel[i].xy) * uv_size; suv = clamp(suv, spot_lights.data[idx].atlas_rect.xy, clamp_max); float d = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), suv, 0.0).r; if (d < splane.z) { @@ -726,7 +726,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) { shadow = 0.0; for (uint i = 0; i < sc_penumbra_shadow_samples; i++) { - vec2 suv = shadow_uv + (disk_rotation * scene_data.penumbra_shadow_kernel[i].xy) * uv_size; + vec2 suv = shadow_uv + (disk_rotation * scene_data_block.data.penumbra_shadow_kernel[i].xy) * uv_size; suv = clamp(suv, spot_lights.data[idx].atlas_rect.xy, clamp_max); shadow += textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(suv, splane.z, 1.0)); } @@ -740,7 +740,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) { } else { //hard shadow vec3 shadow_uv = vec3(splane.xy * spot_lights.data[idx].atlas_rect.zw + spot_lights.data[idx].atlas_rect.xy, splane.z); - shadow = sample_pcf_shadow(shadow_atlas, spot_lights.data[idx].soft_shadow_scale * scene_data.shadow_atlas_pixel_size, shadow_uv); + shadow = sample_pcf_shadow(shadow_atlas, spot_lights.data[idx].soft_shadow_scale * scene_data_block.data.shadow_atlas_pixel_size, shadow_uv); } return shadow; @@ -869,7 +869,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v diffuse_light, specular_light); } -void reflection_process(uint ref_index, vec3 vertex, vec3 normal, float roughness, vec3 ambient_light, vec3 specular_light, inout vec4 ambient_accum, inout vec4 reflection_accum) { +void reflection_process(uint ref_index, vec3 view, vec3 vertex, vec3 normal, float roughness, vec3 ambient_light, vec3 specular_light, inout vec4 ambient_accum, inout vec4 reflection_accum) { vec3 box_extents = reflections.data[ref_index].box_extents; vec3 local_pos = (reflections.data[ref_index].local_matrix * vec4(vertex, 1.0)).xyz; @@ -877,7 +877,7 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 normal, float roughnes return; } - vec3 ref_vec = normalize(reflect(vertex, normal)); + vec3 ref_vec = normalize(reflect(-view, normal)); vec3 inner_pos = abs(local_pos / box_extents); float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z)); diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl index b6ba244665..26d0de46c2 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl @@ -114,6 +114,8 @@ invariant gl_Position; #GLOBALS +#define scene_data scene_data_block.data + void main() { vec4 instance_custom = vec4(0.0); #if defined(COLOR_USED) @@ -527,13 +529,13 @@ layout(location = 0) out mediump vec4 frag_color; */ vec4 fog_process(vec3 vertex) { - vec3 fog_color = scene_data.fog_light_color; + vec3 fog_color = scene_data_block.data.fog_light_color; - if (scene_data.fog_aerial_perspective > 0.0) { + if (scene_data_block.data.fog_aerial_perspective > 0.0) { vec3 sky_fog_color = vec3(0.0); - vec3 cube_view = scene_data.radiance_inverse_xform * vertex; + vec3 cube_view = scene_data_block.data.radiance_inverse_xform * vertex; // mip_level always reads from the second mipmap and higher so the fog is always slightly blurred - float mip_level = mix(1.0 / MAX_ROUGHNESS_LOD, 1.0, 1.0 - (abs(vertex.z) - scene_data.z_near) / (scene_data.z_far - scene_data.z_near)); + float mip_level = mix(1.0 / MAX_ROUGHNESS_LOD, 1.0, 1.0 - (abs(vertex.z) - scene_data_block.data.z_near) / (scene_data_block.data.z_far - scene_data_block.data.z_near)); #ifdef USE_RADIANCE_CUBEMAP_ARRAY float lod, blend; blend = modf(mip_level * MAX_ROUGHNESS_LOD, lod); @@ -542,29 +544,29 @@ vec4 fog_process(vec3 vertex) { #else sky_fog_color = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_view, mip_level * MAX_ROUGHNESS_LOD).rgb; #endif //USE_RADIANCE_CUBEMAP_ARRAY - fog_color = mix(fog_color, sky_fog_color, scene_data.fog_aerial_perspective); + fog_color = mix(fog_color, sky_fog_color, scene_data_block.data.fog_aerial_perspective); } - if (scene_data.fog_sun_scatter > 0.001) { + if (scene_data_block.data.fog_sun_scatter > 0.001) { vec4 sun_scatter = vec4(0.0); float sun_total = 0.0; vec3 view = normalize(vertex); - for (uint i = 0; i < scene_data.directional_light_count; i++) { + for (uint i = 0; i < scene_data_block.data.directional_light_count; i++) { vec3 light_color = directional_lights.data[i].color * directional_lights.data[i].energy; float light_amount = pow(max(dot(view, directional_lights.data[i].direction), 0.0), 8.0); - fog_color += light_color * light_amount * scene_data.fog_sun_scatter; + fog_color += light_color * light_amount * scene_data_block.data.fog_sun_scatter; } } - float fog_amount = 1.0 - exp(min(0.0, -length(vertex) * scene_data.fog_density)); + float fog_amount = 1.0 - exp(min(0.0, -length(vertex) * scene_data_block.data.fog_density)); - if (abs(scene_data.fog_height_density) >= 0.0001) { - float y = (scene_data.inv_view_matrix * vec4(vertex, 1.0)).y; + if (abs(scene_data_block.data.fog_height_density) >= 0.0001) { + float y = (scene_data_block.data.inv_view_matrix * vec4(vertex, 1.0)).y; - float y_dist = y - scene_data.fog_height; + float y_dist = y - scene_data_block.data.fog_height; - float vfog_amount = 1.0 - exp(min(0.0, y_dist * scene_data.fog_height_density)); + float vfog_amount = 1.0 - exp(min(0.0, y_dist * scene_data_block.data.fog_height_density)); fog_amount = max(vfog_amount, fog_amount); } @@ -574,6 +576,8 @@ vec4 fog_process(vec3 vertex) { #endif //!MODE_RENDER DEPTH +#define scene_data scene_data_block.data + void main() { #ifdef MODE_DUAL_PARABOLOID @@ -583,7 +587,11 @@ void main() { //lay out everything, whatever is unused is optimized away anyway vec3 vertex = vertex_interp; +#ifdef USE_MULTIVIEW + vec3 view = -normalize(vertex_interp - scene_data.eye_offset[ViewIndex].xyz); +#else vec3 view = -normalize(vertex_interp); +#endif vec3 albedo = vec3(1.0); vec3 backlight = vec3(0.0); vec4 transmittance_color = vec4(0.0); @@ -650,7 +658,7 @@ void main() { float normal_map_depth = 1.0; - vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size + scene_data.screen_pixel_size * 0.5; //account for center + vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size; float sss_strength = 0.0; @@ -924,7 +932,7 @@ void main() { #endif // !USE_LIGHTMAP #if defined(CUSTOM_IRRADIANCE_USED) - ambient_light = mix(specular_light, custom_irradiance.rgb, custom_irradiance.a); + ambient_light = mix(ambient_light, custom_irradiance.rgb, custom_irradiance.a); #endif // CUSTOM_IRRADIANCE_USED #ifdef LIGHT_CLEARCOAT_USED @@ -1048,7 +1056,7 @@ void main() { #else vec3 bent_normal = normal; #endif - reflection_process(reflection_index, vertex, bent_normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum); + reflection_process(reflection_index, view, vertex, bent_normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum); } if (reflection_accum.a > 0.0) { diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl index 91ef19ab67..7413d8730a 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl @@ -125,7 +125,7 @@ global_variables; /* Set 1: Render Pass (changes per render pass) */ -layout(set = 1, binding = 0, std140) uniform SceneData { +struct SceneData { highp mat4 projection_matrix; highp mat4 inv_projection_matrix; highp mat4 inv_view_matrix; @@ -134,6 +134,7 @@ layout(set = 1, binding = 0, std140) uniform SceneData { // only used for multiview highp mat4 projection_matrix_view[MAX_VIEWS]; highp mat4 inv_projection_matrix_view[MAX_VIEWS]; + highp vec4 eye_offset[MAX_VIEWS]; highp vec2 viewport_size; highp vec2 screen_pixel_size; @@ -189,8 +190,12 @@ layout(set = 1, binding = 0, std140) uniform SceneData { uint pad1; uint pad2; uint pad3; +}; + +layout(set = 1, binding = 0, std140) uniform SceneDataBlock { + SceneData data; } -scene_data; +scene_data_block; #ifdef USE_RADIANCE_CUBEMAP_ARRAY diff --git a/servers/rendering/renderer_rd/shaders/skeleton.glsl b/servers/rendering/renderer_rd/shaders/skeleton.glsl index 4ef6a26443..a893a66c94 100644 --- a/servers/rendering/renderer_rd/shaders/skeleton.glsl +++ b/servers/rendering/renderer_rd/shaders/skeleton.glsl @@ -160,7 +160,7 @@ void main() { } if (params.has_tangent) { - blend_tangent += decode_abgr_2_10_10_10(src_blend_shapes.data[base_offset]).rgb; + blend_tangent += decode_abgr_2_10_10_10(src_blend_shapes.data[base_offset]).rgb * w; } blend_total += w; @@ -174,8 +174,8 @@ void main() { } vertex += blend_vertex; - normal += normalize(normal + blend_normal); - tangent.rgb += normalize(tangent.rgb + blend_tangent); + normal = normalize(normal + blend_normal); + tangent.rgb = normalize(tangent.rgb + blend_tangent); } if (params.has_skeleton) { diff --git a/servers/rendering/renderer_rd/shaders/ssil_blur.glsl b/servers/rendering/renderer_rd/shaders/ssil_blur.glsl index ee21d46a74..47c56571f6 100644 --- a/servers/rendering/renderer_rd/shaders/ssil_blur.glsl +++ b/servers/rendering/renderer_rd/shaders/ssil_blur.glsl @@ -1,3 +1,23 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016, Intel Corporation +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to the following conditions: +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of +// the Software. +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// File changes (yyyy-mm-dd) +// 2016-09-07: filip.strugar@intel.com: first commit +// 2020-12-05: clayjohn: convert to Vulkan and Godot +// 2021-05-27: clayjohn: convert SSAO to SSIL +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + #[compute] #version 450 diff --git a/servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl b/servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl index 8818f8cada..6b6b02739d 100644 --- a/servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl +++ b/servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl @@ -15,6 +15,7 @@ // File changes (yyyy-mm-dd) // 2016-09-07: filip.strugar@intel.com: first commit // 2020-12-05: clayjohn: convert to Vulkan and Godot +// 2021-05-27: clayjohn: convert SSAO to SSIL /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #[compute] diff --git a/servers/rendering/renderer_rd/shaders/ssil_interleave.glsl b/servers/rendering/renderer_rd/shaders/ssil_interleave.glsl index fa4309353d..9e86ac0cf0 100644 --- a/servers/rendering/renderer_rd/shaders/ssil_interleave.glsl +++ b/servers/rendering/renderer_rd/shaders/ssil_interleave.glsl @@ -1,3 +1,23 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2016, Intel Corporation +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to the following conditions: +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of +// the Software. +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// File changes (yyyy-mm-dd) +// 2016-09-07: filip.strugar@intel.com: first commit +// 2020-12-05: clayjohn: convert to Vulkan and Godot +// 2021-05-27: clayjohn: convert SSAO to SSIL +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + #[compute] #version 450 diff --git a/servers/rendering/renderer_rd/shaders/taa_resolve.glsl b/servers/rendering/renderer_rd/shaders/taa_resolve.glsl new file mode 100644 index 0000000000..ddd984ad83 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/taa_resolve.glsl @@ -0,0 +1,394 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright(c) 2016-2022 Panos Karabelas +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +// copies of the Software, and to permit persons to whom the Software is furnished +// to do so, subject to the following conditions : +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +/////////////////////////////////////////////////////////////////////////////////// +// File changes (yyyy-mm-dd) +// 2022-05-06: Panos Karabelas: first commit +// 2020-12-05: Joan Fons: convert to Vulkan and Godot +/////////////////////////////////////////////////////////////////////////////////// + +#[compute] + +#version 450 + +#VERSION_DEFINES + +// Based on Spartan Engine's TAA implementation (without TAA upscale). +// <https://github.com/PanosK92/SpartanEngine/blob/a8338d0609b85dc32f3732a5c27fb4463816a3b9/Data/shaders/temporal_antialiasing.hlsl> + +#define USE_SUBGROUPS + +#define GROUP_SIZE 8 +#define FLT_MIN 0.00000001 +#define FLT_MAX 32767.0 +#define RPC_9 0.11111111111 +#define RPC_16 0.0625 + +#ifdef USE_SUBGROUPS +layout(local_size_x = GROUP_SIZE, local_size_y = GROUP_SIZE, local_size_z = 1) in; +#endif + +layout(rgba16f, set = 0, binding = 0) uniform restrict readonly image2D color_buffer; +layout(set = 0, binding = 1) uniform sampler2D depth_buffer; +layout(rg16f, set = 0, binding = 2) uniform restrict readonly image2D velocity_buffer; +layout(rg16f, set = 0, binding = 3) uniform restrict readonly image2D last_velocity_buffer; +layout(set = 0, binding = 4) uniform sampler2D history_buffer; +layout(rgba16f, set = 0, binding = 5) uniform restrict writeonly image2D output_buffer; + +layout(push_constant, std430) uniform Params { + vec2 resolution; + float disocclusion_threshold; // 0.1 / max(params.resolution.x, params.resolution.y + float disocclusion_scale; +} +params; + +const ivec2 kOffsets3x3[9] = { + ivec2(-1, -1), + ivec2(0, -1), + ivec2(1, -1), + ivec2(-1, 0), + ivec2(0, 0), + ivec2(1, 0), + ivec2(-1, 1), + ivec2(0, 1), + ivec2(1, 1), +}; + +/*------------------------------------------------------------------------------ + THREAD GROUP SHARED MEMORY (LDS) +------------------------------------------------------------------------------*/ + +const int kBorderSize = 1; +const int kGroupSize = GROUP_SIZE; +const int kTileDimension = kGroupSize + kBorderSize * 2; +const int kTileDimension2 = kTileDimension * kTileDimension; + +vec3 reinhard(vec3 hdr) { + return hdr / (hdr + 1.0); +} +vec3 reinhard_inverse(vec3 sdr) { + return sdr / (1.0 - sdr); +} + +float get_depth(ivec2 thread_id) { + return texelFetch(depth_buffer, thread_id, 0).r; +} + +#ifdef USE_SUBGROUPS +shared vec3 tile_color[kTileDimension][kTileDimension]; +shared float tile_depth[kTileDimension][kTileDimension]; + +vec3 load_color(uvec2 group_thread_id) { + group_thread_id += kBorderSize; + return tile_color[group_thread_id.x][group_thread_id.y]; +} + +void store_color(uvec2 group_thread_id, vec3 color) { + tile_color[group_thread_id.x][group_thread_id.y] = color; +} + +float load_depth(uvec2 group_thread_id) { + group_thread_id += kBorderSize; + return tile_depth[group_thread_id.x][group_thread_id.y]; +} + +void store_depth(uvec2 group_thread_id, float depth) { + tile_depth[group_thread_id.x][group_thread_id.y] = depth; +} + +void store_color_depth(uvec2 group_thread_id, ivec2 thread_id) { + // out of bounds clamp + thread_id = clamp(thread_id, ivec2(0, 0), ivec2(params.resolution) - ivec2(1, 1)); + + store_color(group_thread_id, imageLoad(color_buffer, thread_id).rgb); + store_depth(group_thread_id, get_depth(thread_id)); +} + +void populate_group_shared_memory(uvec2 group_id, uint group_index) { + // Populate group shared memory + ivec2 group_top_left = ivec2(group_id) * kGroupSize - kBorderSize; + if (group_index < (kTileDimension2 >> 2)) { + ivec2 group_thread_id_1 = ivec2(group_index % kTileDimension, group_index / kTileDimension); + ivec2 group_thread_id_2 = ivec2((group_index + (kTileDimension2 >> 2)) % kTileDimension, (group_index + (kTileDimension2 >> 2)) / kTileDimension); + ivec2 group_thread_id_3 = ivec2((group_index + (kTileDimension2 >> 1)) % kTileDimension, (group_index + (kTileDimension2 >> 1)) / kTileDimension); + ivec2 group_thread_id_4 = ivec2((group_index + kTileDimension2 * 3 / 4) % kTileDimension, (group_index + kTileDimension2 * 3 / 4) / kTileDimension); + + store_color_depth(group_thread_id_1, group_top_left + group_thread_id_1); + store_color_depth(group_thread_id_2, group_top_left + group_thread_id_2); + store_color_depth(group_thread_id_3, group_top_left + group_thread_id_3); + store_color_depth(group_thread_id_4, group_top_left + group_thread_id_4); + } + + // Wait for group threads to load store data. + groupMemoryBarrier(); + barrier(); +} +#else +vec3 load_color(uvec2 screen_pos) { + return imageLoad(color_buffer, ivec2(screen_pos)).rgb; +} + +float load_depth(uvec2 screen_pos) { + return get_depth(ivec2(screen_pos)); +} +#endif + +/*------------------------------------------------------------------------------ + VELOCITY +------------------------------------------------------------------------------*/ + +void depth_test_min(uvec2 pos, inout float min_depth, inout uvec2 min_pos) { + float depth = load_depth(pos); + + if (depth < min_depth) { + min_depth = depth; + min_pos = pos; + } +} + +// Returns velocity with closest depth (3x3 neighborhood) +void get_closest_pixel_velocity_3x3(in uvec2 group_pos, uvec2 group_top_left, out vec2 velocity) { + float min_depth = 1.0; + uvec2 min_pos = group_pos; + + depth_test_min(group_pos + kOffsets3x3[0], min_depth, min_pos); + depth_test_min(group_pos + kOffsets3x3[1], min_depth, min_pos); + depth_test_min(group_pos + kOffsets3x3[2], min_depth, min_pos); + depth_test_min(group_pos + kOffsets3x3[3], min_depth, min_pos); + depth_test_min(group_pos + kOffsets3x3[4], min_depth, min_pos); + depth_test_min(group_pos + kOffsets3x3[5], min_depth, min_pos); + depth_test_min(group_pos + kOffsets3x3[6], min_depth, min_pos); + depth_test_min(group_pos + kOffsets3x3[7], min_depth, min_pos); + depth_test_min(group_pos + kOffsets3x3[8], min_depth, min_pos); + + // Velocity out + velocity = imageLoad(velocity_buffer, ivec2(group_top_left + min_pos)).xy; +} + +/*------------------------------------------------------------------------------ + HISTORY SAMPLING +------------------------------------------------------------------------------*/ + +vec3 sample_catmull_rom_9(sampler2D stex, vec2 uv, vec2 resolution) { + // Source: https://gist.github.com/TheRealMJP/c83b8c0f46b63f3a88a5986f4fa982b1 + // License: https://gist.github.com/TheRealMJP/bc503b0b87b643d3505d41eab8b332ae + + // We're going to sample a a 4x4 grid of texels surrounding the target UV coordinate. We'll do this by rounding + // down the sample location to get the exact center of our "starting" texel. The starting texel will be at + // location [1, 1] in the grid, where [0, 0] is the top left corner. + vec2 sample_pos = uv * resolution; + vec2 texPos1 = floor(sample_pos - 0.5f) + 0.5f; + + // Compute the fractional offset from our starting texel to our original sample location, which we'll + // feed into the Catmull-Rom spline function to get our filter weights. + vec2 f = sample_pos - texPos1; + + // Compute the Catmull-Rom weights using the fractional offset that we calculated earlier. + // These equations are pre-expanded based on our knowledge of where the texels will be located, + // which lets us avoid having to evaluate a piece-wise function. + vec2 w0 = f * (-0.5f + f * (1.0f - 0.5f * f)); + vec2 w1 = 1.0f + f * f * (-2.5f + 1.5f * f); + vec2 w2 = f * (0.5f + f * (2.0f - 1.5f * f)); + vec2 w3 = f * f * (-0.5f + 0.5f * f); + + // Work out weighting factors and sampling offsets that will let us use bilinear filtering to + // simultaneously evaluate the middle 2 samples from the 4x4 grid. + vec2 w12 = w1 + w2; + vec2 offset12 = w2 / (w1 + w2); + + // Compute the final UV coordinates we'll use for sampling the texture + vec2 texPos0 = texPos1 - 1.0f; + vec2 texPos3 = texPos1 + 2.0f; + vec2 texPos12 = texPos1 + offset12; + + texPos0 /= resolution; + texPos3 /= resolution; + texPos12 /= resolution; + + vec3 result = vec3(0.0f, 0.0f, 0.0f); + + result += textureLod(stex, vec2(texPos0.x, texPos0.y), 0.0).xyz * w0.x * w0.y; + result += textureLod(stex, vec2(texPos12.x, texPos0.y), 0.0).xyz * w12.x * w0.y; + result += textureLod(stex, vec2(texPos3.x, texPos0.y), 0.0).xyz * w3.x * w0.y; + + result += textureLod(stex, vec2(texPos0.x, texPos12.y), 0.0).xyz * w0.x * w12.y; + result += textureLod(stex, vec2(texPos12.x, texPos12.y), 0.0).xyz * w12.x * w12.y; + result += textureLod(stex, vec2(texPos3.x, texPos12.y), 0.0).xyz * w3.x * w12.y; + + result += textureLod(stex, vec2(texPos0.x, texPos3.y), 0.0).xyz * w0.x * w3.y; + result += textureLod(stex, vec2(texPos12.x, texPos3.y), 0.0).xyz * w12.x * w3.y; + result += textureLod(stex, vec2(texPos3.x, texPos3.y), 0.0).xyz * w3.x * w3.y; + + return max(result, 0.0f); +} + +/*------------------------------------------------------------------------------ + HISTORY CLIPPING +------------------------------------------------------------------------------*/ + +// Based on "Temporal Reprojection Anti-Aliasing" - https://github.com/playdeadgames/temporal +vec3 clip_aabb(vec3 aabb_min, vec3 aabb_max, vec3 p, vec3 q) { + vec3 r = q - p; + vec3 rmax = (aabb_max - p.xyz); + vec3 rmin = (aabb_min - p.xyz); + + if (r.x > rmax.x + FLT_MIN) + r *= (rmax.x / r.x); + if (r.y > rmax.y + FLT_MIN) + r *= (rmax.y / r.y); + if (r.z > rmax.z + FLT_MIN) + r *= (rmax.z / r.z); + + if (r.x < rmin.x - FLT_MIN) + r *= (rmin.x / r.x); + if (r.y < rmin.y - FLT_MIN) + r *= (rmin.y / r.y); + if (r.z < rmin.z - FLT_MIN) + r *= (rmin.z / r.z); + + return p + r; +} + +// Clip history to the neighbourhood of the current sample +vec3 clip_history_3x3(uvec2 group_pos, vec3 color_history, vec2 velocity_closest) { + // Sample a 3x3 neighbourhood + vec3 s1 = load_color(group_pos + kOffsets3x3[0]); + vec3 s2 = load_color(group_pos + kOffsets3x3[1]); + vec3 s3 = load_color(group_pos + kOffsets3x3[2]); + vec3 s4 = load_color(group_pos + kOffsets3x3[3]); + vec3 s5 = load_color(group_pos + kOffsets3x3[4]); + vec3 s6 = load_color(group_pos + kOffsets3x3[5]); + vec3 s7 = load_color(group_pos + kOffsets3x3[6]); + vec3 s8 = load_color(group_pos + kOffsets3x3[7]); + vec3 s9 = load_color(group_pos + kOffsets3x3[8]); + + // Compute min and max (with an adaptive box size, which greatly reduces ghosting) + vec3 color_avg = (s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9) * RPC_9; + vec3 color_avg2 = ((s1 * s1) + (s2 * s2) + (s3 * s3) + (s4 * s4) + (s5 * s5) + (s6 * s6) + (s7 * s7) + (s8 * s8) + (s9 * s9)) * RPC_9; + float box_size = mix(0.0f, 2.5f, smoothstep(0.02f, 0.0f, length(velocity_closest))); + vec3 dev = sqrt(abs(color_avg2 - (color_avg * color_avg))) * box_size; + vec3 color_min = color_avg - dev; + vec3 color_max = color_avg + dev; + + // Variance clipping + vec3 color = clip_aabb(color_min, color_max, clamp(color_avg, color_min, color_max), color_history); + + // Clamp to prevent NaNs + color = clamp(color, FLT_MIN, FLT_MAX); + + return color; +} + +/*------------------------------------------------------------------------------ + TAA +------------------------------------------------------------------------------*/ + +const vec3 lumCoeff = vec3(0.299f, 0.587f, 0.114f); + +float luminance(vec3 color) { + return max(dot(color, lumCoeff), 0.0001f); +} + +float get_factor_disocclusion(vec2 uv_reprojected, vec2 velocity) { + vec2 velocity_previous = imageLoad(last_velocity_buffer, ivec2(uv_reprojected * params.resolution)).xy; + vec2 velocity_texels = velocity * params.resolution; + vec2 prev_velocity_texels = velocity_previous * params.resolution; + float disocclusion = length(prev_velocity_texels - velocity_texels) - params.disocclusion_threshold; + return clamp(disocclusion * params.disocclusion_scale, 0.0, 1.0); +} + +vec3 temporal_antialiasing(uvec2 pos_group_top_left, uvec2 pos_group, uvec2 pos_screen, vec2 uv, sampler2D tex_history) { + // Get the velocity of the current pixel + vec2 velocity = imageLoad(velocity_buffer, ivec2(pos_screen)).xy; + + // Get reprojected uv + vec2 uv_reprojected = uv - velocity; + + // Get input color + vec3 color_input = load_color(pos_group); + + // Get history color (catmull-rom reduces a lot of the blurring that you get under motion) + vec3 color_history = sample_catmull_rom_9(tex_history, uv_reprojected, params.resolution).rgb; + + // Clip history to the neighbourhood of the current sample (fixes a lot of the ghosting). + vec2 velocity_closest = vec2(0.0); // This is best done by using the velocity with the closest depth. + get_closest_pixel_velocity_3x3(pos_group, pos_group_top_left, velocity_closest); + color_history = clip_history_3x3(pos_group, color_history, velocity_closest); + + // Compute blend factor + float blend_factor = RPC_16; // We want to be able to accumulate as many jitter samples as we generated, that is, 16. + { + // If re-projected UV is out of screen, converge to current color immediatel + float factor_screen = any(lessThan(uv_reprojected, vec2(0.0))) || any(greaterThan(uv_reprojected, vec2(1.0))) ? 1.0 : 0.0; + + // Increase blend factor when there is disocclusion (fixes a lot of the remaining ghosting). + float factor_disocclusion = get_factor_disocclusion(uv_reprojected, velocity); + + // Add to the blend factor + blend_factor = clamp(blend_factor + factor_screen + factor_disocclusion, 0.0, 1.0); + } + + // Resolve + vec3 color_resolved = vec3(0.0); + { + // Tonemap + color_history = reinhard(color_history); + color_input = reinhard(color_input); + + // Reduce flickering + float lum_color = luminance(color_input); + float lum_history = luminance(color_history); + float diff = abs(lum_color - lum_history) / max(lum_color, max(lum_history, 1.001)); + diff = 1.0 - diff; + diff = diff * diff; + blend_factor = mix(0.0, blend_factor, diff); + + // Lerp/blend + color_resolved = mix(color_history, color_input, blend_factor); + + // Inverse tonemap + color_resolved = reinhard_inverse(color_resolved); + } + + return color_resolved; +} + +void main() { +#ifdef USE_SUBGROUPS + populate_group_shared_memory(gl_WorkGroupID.xy, gl_LocalInvocationIndex); +#endif + + // Out of bounds check + if (any(greaterThanEqual(vec2(gl_GlobalInvocationID.xy), params.resolution))) { + return; + } + +#ifdef USE_SUBGROUPS + const uvec2 pos_group = gl_LocalInvocationID.xy; + const uvec2 pos_group_top_left = gl_WorkGroupID.xy * kGroupSize - kBorderSize; +#else + const uvec2 pos_group = gl_GlobalInvocationID.xy; + const uvec2 pos_group_top_left = uvec2(0, 0); +#endif + const uvec2 pos_screen = gl_GlobalInvocationID.xy; + const vec2 uv = (gl_GlobalInvocationID.xy + 0.5f) / params.resolution; + + vec3 result = temporal_antialiasing(pos_group_top_left, pos_group, pos_screen, uv, history_buffer); + imageStore(output_buffer, ivec2(gl_GlobalInvocationID.xy), vec4(result, 1.0)); +} diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl index a2a4c91894..eee609fb48 100644 --- a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl +++ b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl @@ -186,12 +186,31 @@ void main() { float sdf = -1.0; if (params.shape == 0) { - //Ellipsoid + // Ellipsoid // https://www.shadertoy.com/view/tdS3DG float k0 = length(local_pos.xyz / params.extents); float k1 = length(local_pos.xyz / (params.extents * params.extents)); sdf = k0 * (k0 - 1.0) / k1; } else if (params.shape == 1) { + // Cone + // https://iquilezles.org/www/articles/distfunctions/distfunctions.htm + + // Compute the cone angle automatically to fit within the volume's extents. + float inv_height = 1.0 / max(0.001, params.extents.y); + float radius = 1.0 / max(0.001, (min(params.extents.x, params.extents.z) * 0.5)); + float hypotenuse = sqrt(radius * radius + inv_height * inv_height); + float rsin = radius / hypotenuse; + float rcos = inv_height / hypotenuse; + vec2 c = vec2(rsin, rcos); + + float q = length(local_pos.xz); + sdf = max(dot(c, vec2(q, local_pos.y - params.extents.y)), -params.extents.y - local_pos.y); + } else if (params.shape == 2) { + // Cylinder + // https://iquilezles.org/www/articles/distfunctions/distfunctions.htm + vec2 d = abs(vec2(length(local_pos.xz), local_pos.y)) - vec2(min(params.extents.x, params.extents.z), params.extents.y); + sdf = min(max(d.x, d.y), 0.0) + length(max(d, 0.0)); + } else if (params.shape == 3) { // Box // https://iquilezles.org/www/articles/distfunctions/distfunctions.htm vec3 q = abs(local_pos.xyz) - params.extents; @@ -199,7 +218,7 @@ void main() { } float cull_mask = 1.0; //used to cull cells that do not contribute - if (params.shape <= 1) { + if (params.shape <= 3) { #ifndef SDF_USED cull_mask = 1.0 - smoothstep(-0.1, 0.0, sdf); #endif diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl b/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl index 347fd13b28..fdbd7d3e35 100644 --- a/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl +++ b/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl @@ -53,7 +53,6 @@ layout(set = 0, binding = 7) uniform sampler linear_sampler; #ifdef MODE_DENSITY layout(rgba16f, set = 0, binding = 8) uniform restrict writeonly image3D density_map; -layout(rgba16f, set = 0, binding = 9) uniform restrict readonly image3D fog_map; //unused #endif #ifdef MODE_FOG diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp index 56a4525b8e..e65f676785 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp @@ -156,12 +156,12 @@ void LightStorage::light_set_param(RID p_light, RS::LightParam p_param, float p_ case RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE: case RS::LIGHT_PARAM_SHADOW_BIAS: { light->version++; - light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT); + light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT); } break; case RS::LIGHT_PARAM_SIZE: { if ((light->param[p_param] > CMP_EPSILON) != (p_value > CMP_EPSILON)) { //changing from no size to size and the opposite - light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR); + light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR); } } break; default: { @@ -177,7 +177,7 @@ void LightStorage::light_set_shadow(RID p_light, bool p_enabled) { light->shadow = p_enabled; light->version++; - light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT); + light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT); } void LightStorage::light_set_projector(RID p_light, RID p_texture) { @@ -199,7 +199,7 @@ void LightStorage::light_set_projector(RID p_light, RID p_texture) { if (light->projector.is_valid()) { texture_storage->texture_add_to_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI); } - light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR); + light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR); } } @@ -217,7 +217,7 @@ void LightStorage::light_set_cull_mask(RID p_light, uint32_t p_mask) { light->cull_mask = p_mask; light->version++; - light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT); + light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT); } void LightStorage::light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) { @@ -237,7 +237,7 @@ void LightStorage::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) light->reverse_cull = p_enabled; light->version++; - light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT); + light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT); } void LightStorage::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) { @@ -247,7 +247,7 @@ void LightStorage::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mod light->bake_mode = p_bake_mode; light->version++; - light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT); + light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT); } void LightStorage::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) { @@ -257,7 +257,7 @@ void LightStorage::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) light->max_sdfgi_cascade = p_cascade; light->version++; - light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT); + light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT); } void LightStorage::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) { @@ -267,7 +267,7 @@ void LightStorage::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMo light->omni_shadow_mode = p_mode; light->version++; - light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT); + light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT); } RS::LightOmniShadowMode LightStorage::light_omni_get_shadow_mode(RID p_light) { @@ -283,7 +283,7 @@ void LightStorage::light_directional_set_shadow_mode(RID p_light, RS::LightDirec light->directional_shadow_mode = p_mode; light->version++; - light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT); + light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT); } void LightStorage::light_directional_set_blend_splits(RID p_light, bool p_enable) { @@ -292,7 +292,7 @@ void LightStorage::light_directional_set_blend_splits(RID p_light, bool p_enable light->directional_blend_splits = p_enable; light->version++; - light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT); + light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT); } bool LightStorage::light_directional_get_blend_splits(RID p_light) const { @@ -387,7 +387,7 @@ void LightStorage::reflection_probe_set_update_mode(RID p_probe, RS::ReflectionP ERR_FAIL_COND(!reflection_probe); reflection_probe->update_mode = p_mode; - reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE); + reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE); } void LightStorage::reflection_probe_set_intensity(RID p_probe, float p_intensity) { @@ -424,7 +424,7 @@ void LightStorage::reflection_probe_set_max_distance(RID p_probe, float p_distan reflection_probe->max_distance = p_distance; - reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE); + reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE); } void LightStorage::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) { @@ -435,7 +435,7 @@ void LightStorage::reflection_probe_set_extents(RID p_probe, const Vector3 &p_ex return; } reflection_probe->extents = p_extents; - reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE); + reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE); } void LightStorage::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) { @@ -443,7 +443,7 @@ void LightStorage::reflection_probe_set_origin_offset(RID p_probe, const Vector3 ERR_FAIL_COND(!reflection_probe); reflection_probe->origin_offset = p_offset; - reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE); + reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE); } void LightStorage::reflection_probe_set_as_interior(RID p_probe, bool p_enable) { @@ -451,7 +451,7 @@ void LightStorage::reflection_probe_set_as_interior(RID p_probe, bool p_enable) ERR_FAIL_COND(!reflection_probe); reflection_probe->interior = p_enable; - reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE); + reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE); } void LightStorage::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) { @@ -466,7 +466,7 @@ void LightStorage::reflection_probe_set_enable_shadows(RID p_probe, bool p_enabl ERR_FAIL_COND(!reflection_probe); reflection_probe->enable_shadows = p_enable; - reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE); + reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE); } void LightStorage::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) { @@ -474,7 +474,7 @@ void LightStorage::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers ERR_FAIL_COND(!reflection_probe); reflection_probe->cull_mask = p_layers; - reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE); + reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE); } void LightStorage::reflection_probe_set_resolution(RID p_probe, int p_resolution) { @@ -491,7 +491,7 @@ void LightStorage::reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ reflection_probe->mesh_lod_threshold = p_ratio; - reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE); + reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE); } AABB LightStorage::reflection_probe_get_aabb(RID p_probe) const { diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h index 3cc455692d..fb25e4da7e 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h @@ -35,6 +35,7 @@ #include "core/templates/rid_owner.h" #include "core/templates/self_list.h" #include "servers/rendering/storage/light_storage.h" +#include "servers/rendering/storage/utilities.h" namespace RendererRD { @@ -61,7 +62,7 @@ struct Light { RS::LightDirectionalSkyMode directional_sky_mode = RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY; uint64_t version = 0; - RendererStorage::Dependency dependency; + Dependency dependency; }; /* REFLECTION PROBE */ @@ -82,7 +83,7 @@ struct ReflectionProbe { uint32_t cull_mask = (1 << 20) - 1; float mesh_lod_threshold = 0.01; - RendererStorage::Dependency dependency; + Dependency dependency; }; /* LIGHTMAP */ @@ -104,7 +105,7 @@ struct Lightmap { int32_t over = EMPTY_LEAF, under = EMPTY_LEAF; }; - RendererStorage::Dependency dependency; + Dependency dependency; }; class LightStorage : public RendererLightStorage { diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp index 550fc7d788..fcd25852eb 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp @@ -896,7 +896,7 @@ _FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, /////////////////////////////////////////////////////////////////////////// // MaterialData -void MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) { +void MaterialData::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) { MaterialStorage *material_storage = MaterialStorage::get_singleton(); bool uses_global_buffer = false; @@ -943,11 +943,11 @@ void MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::S ERR_CONTINUE(offset + size > p_buffer_size); #endif uint8_t *data = &p_buffer[offset]; - const Map<StringName, Variant>::Element *V = p_parameters.find(E.key); + HashMap<StringName, Variant>::ConstIterator V = p_parameters.find(E.key); if (V) { //user provided - _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, V->get(), data, p_use_linear_color); + _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, V->value, data, p_use_linear_color); } else if (E.value.default_value.size()) { //default value @@ -955,7 +955,7 @@ void MaterialData::update_uniform_buffer(const Map<StringName, ShaderLanguage::S //value=E.value.default_value; } else { //zero because it was not provided - if ((E.value.type == ShaderLanguage::TYPE_VEC3 || E.value.type == ShaderLanguage::TYPE_VEC4) && E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) { + if ((E.value.type == ShaderLanguage::TYPE_VEC3 || E.value.type == ShaderLanguage::TYPE_VEC4) && E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SOURCE_COLOR) { //colors must be set as black, with alpha as 1.0 _fill_std140_variant_ubo_value(E.value.type, E.value.array_size, Color(0, 0, 0, 1), data, p_use_linear_color); } else { @@ -1001,7 +1001,7 @@ MaterialData::~MaterialData() { } } -void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) { +void 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) { TextureStorage *texture_storage = TextureStorage::get_singleton(); MaterialStorage *material_storage = MaterialStorage::get_singleton(); @@ -1029,12 +1029,12 @@ void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!."); } else { - Map<StringName, uint64_t>::Element *E = used_global_textures.find(uniform_name); + HashMap<StringName, uint64_t>::Iterator E = used_global_textures.find(uniform_name); if (!E) { E = used_global_textures.insert(uniform_name, global_textures_pass); v->texture_materials.insert(self); } else { - E->get() = global_textures_pass; + E->value = global_textures_pass; } textures.push_back(v->override.get_type() != Variant::NIL ? v->override : v->value); @@ -1044,10 +1044,10 @@ void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it was removed at some point. Material will not display correctly."); } } else { - const Map<StringName, Variant>::Element *V = p_parameters.find(uniform_name); + HashMap<StringName, Variant>::ConstIterator V = p_parameters.find(uniform_name); if (V) { - if (V->get().is_array()) { - Array array = (Array)V->get(); + if (V->value.is_array()) { + Array array = (Array)V->value; if (uniform_array_size > 0) { for (int j = 0; j < array.size(); j++) { textures.push_back(array[j]); @@ -1058,25 +1058,25 @@ void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, } } } else { - textures.push_back(V->get()); + textures.push_back(V->value); } } if (uniform_array_size > 0) { if (textures.size() < uniform_array_size) { - const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name); + HashMap<StringName, HashMap<int, RID>>::ConstIterator W = p_default_textures.find(uniform_name); for (int j = textures.size(); j < uniform_array_size; j++) { - if (W && W->get().has(j)) { - textures.push_back(W->get()[j]); + if (W && W->value.has(j)) { + textures.push_back(W->value[j]); } else { textures.push_back(RID()); } } } } else if (textures.is_empty()) { - const Map<StringName, Map<int, RID>>::Element *W = p_default_textures.find(uniform_name); - if (W && W->get().has(0)) { - textures.push_back(W->get()[0]); + HashMap<StringName, HashMap<int, RID>>::ConstIterator W = p_default_textures.find(uniform_name); + if (W && W->value.has(0)) { + textures.push_back(W->value[0]); } } } @@ -1090,8 +1090,7 @@ void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, case ShaderLanguage::TYPE_USAMPLER2D: case ShaderLanguage::TYPE_SAMPLER2D: { switch (p_texture_uniforms[i].hint) { - case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: - case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: { + case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_BLACK: { rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK); } break; case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: { @@ -1111,8 +1110,7 @@ void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, case ShaderLanguage::TYPE_SAMPLERCUBE: { switch (p_texture_uniforms[i].hint) { - case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: - case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: { + case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_BLACK: { rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); } break; default: { @@ -1152,7 +1150,7 @@ void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, p_textures[k++] = rd_texture; } } else { - bool srgb = p_use_linear_color && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO); + bool srgb = p_use_linear_color && p_texture_uniforms[i].use_color; for (int j = 0; j < textures.size(); j++) { Texture *tex = TextureStorage::get_singleton()->get_texture(textures[j]); @@ -1190,12 +1188,12 @@ void MaterialData::update_textures(const Map<StringName, Variant> &p_parameters, } { //for textures no longer used, unregister them - List<Map<StringName, uint64_t>::Element *> to_delete; - for (Map<StringName, uint64_t>::Element *E = used_global_textures.front(); E; E = E->next()) { - if (E->get() != global_textures_pass) { - to_delete.push_back(E); + List<StringName> to_delete; + for (KeyValue<StringName, uint64_t> &E : used_global_textures) { + if (E.value != global_textures_pass) { + to_delete.push_back(E.key); - GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E->key()); + GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key); if (v) { v->texture_materials.erase(self); } @@ -1225,7 +1223,7 @@ void MaterialData::free_parameters_uniform_set(RID p_uniform_set) { } } -bool MaterialData::update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) { +bool 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, uint32_t p_barrier) { if ((uint32_t)ubo_data.size() != p_ubo_size) { p_uniform_dirty = true; if (uniform_buffer.is_valid()) { @@ -1979,8 +1977,8 @@ void MaterialStorage::global_variable_set(const StringName &p_name, const Varian } else { //texture MaterialStorage *material_storage = MaterialStorage::get_singleton(); - for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) { - Material *material = material_storage->get_material(E->get()); + for (const RID &E : gv.texture_materials) { + Material *material = material_storage->get_material(E); ERR_CONTINUE(!material); material_storage->_material_queue_update(material, false, true); } @@ -2011,8 +2009,8 @@ void MaterialStorage::global_variable_set_override(const StringName &p_name, con } else { //texture MaterialStorage *material_storage = MaterialStorage::get_singleton(); - for (Set<RID>::Element *E = gv.texture_materials.front(); E; E = E->next()) { - Material *material = material_storage->get_material(E->get()); + for (const RID &E : gv.texture_materials) { + Material *material = material_storage->get_material(E); ERR_CONTINUE(!material); material_storage->_material_queue_update(material, false, true); } @@ -2267,7 +2265,7 @@ void MaterialStorage::shader_free(RID p_rid) { //make material unreference this while (shader->owners.size()) { - material_set_shader(shader->owners.front()->get()->self, RID()); + material_set_shader((*shader->owners.begin())->self, RID()); } //clear data if exists @@ -2305,8 +2303,8 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { shader->data = nullptr; } - for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { - Material *material = E->get(); + for (Material *E : shader->owners) { + Material *material = E; material->shader_type = new_type; if (material->data) { memdelete(material->data); @@ -2322,8 +2320,8 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { shader->type = SHADER_TYPE_MAX; //invalid } - for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { - Material *material = E->get(); + for (Material *E : shader->owners) { + Material *material = E; if (shader->data) { material->data = material_get_data_request_function(new_type)(shader->data); material->data->self = material->self; @@ -2334,7 +2332,7 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { } if (shader->data) { - for (const KeyValue<StringName, Map<int, RID>> &E : shader->default_texture_parameter) { + for (const KeyValue<StringName, HashMap<int, RID>> &E : shader->default_texture_parameter) { for (const KeyValue<int, RID> &E2 : E.value) { shader->data->set_default_texture_param(E.key, E2.value, E2.key); } @@ -2346,9 +2344,9 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) { shader->data->set_code(p_code); } - for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { - Material *material = E->get(); - material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); + for (Material *E : shader->owners) { + Material *material = E; + material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL); _material_queue_update(material, true, true); } } @@ -2373,7 +2371,7 @@ void MaterialStorage::shader_set_default_texture_param(RID p_shader, const Strin if (p_texture.is_valid() && TextureStorage::get_singleton()->owns_texture(p_texture)) { if (!shader->default_texture_parameter.has(p_name)) { - shader->default_texture_parameter[p_name] = Map<int, RID>(); + shader->default_texture_parameter[p_name] = HashMap<int, RID>(); } shader->default_texture_parameter[p_name][p_index] = p_texture; } else { @@ -2388,8 +2386,8 @@ void MaterialStorage::shader_set_default_texture_param(RID p_shader, const Strin if (shader->data) { shader->data->set_default_texture_param(p_name, p_texture, p_index); } - for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { - Material *material = E->get(); + for (Material *E : shader->owners) { + Material *material = E; _material_queue_update(material, false, true); } } @@ -2438,7 +2436,7 @@ void MaterialStorage::_material_uniform_set_erased(void *p_material) { // if a texture is deleted, so re-create it. MaterialStorage::get_singleton()->_material_queue_update(material, false, true); } - material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); + material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL); } } @@ -2468,7 +2466,7 @@ void MaterialStorage::_update_queued_materials() { if (uniforms_changed) { //some implementations such as 3D renderer cache the matreial uniform set, so update is required - material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); + material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL); } } } @@ -2509,7 +2507,7 @@ void MaterialStorage::material_set_shader(RID p_material, RID p_shader) { } if (p_shader.is_null()) { - material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); + material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL); material->shader_id = 0; return; } @@ -2532,7 +2530,7 @@ void MaterialStorage::material_set_shader(RID p_material, RID p_shader) { material->data->set_next_pass(material->next_pass); material->data->set_render_priority(material->priority); //updating happens later - material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); + material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL); _material_queue_update(material, true, true); } @@ -2578,7 +2576,7 @@ void MaterialStorage::material_set_next_pass(RID p_material, RID p_next_material material->data->set_next_pass(p_next_material); } - material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); + material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL); } void MaterialStorage::material_set_render_priority(RID p_material, int priority) { @@ -2628,7 +2626,7 @@ void MaterialStorage::material_get_instance_shader_parameters(RID p_material, Li } } -void MaterialStorage::material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) { +void MaterialStorage::material_update_dependency(RID p_material, DependencyTracker *p_instance) { Material *material = material_owner.get_or_null(p_material); ERR_FAIL_COND(!material); p_instance->update_dependency(&material->dependency); diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h index 0e899e37c8..e35d5e7669 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h @@ -31,12 +31,14 @@ #ifndef MATERIAL_STORAGE_RD_H #define MATERIAL_STORAGE_RD_H +#include "core/math/camera_matrix.h" #include "core/templates/local_vector.h" #include "core/templates/rid_owner.h" #include "core/templates/self_list.h" #include "servers/rendering/shader_compiler.h" #include "servers/rendering/shader_language.h" #include "servers/rendering/storage/material_storage.h" +#include "servers/rendering/storage/utilities.h" namespace RendererRD { @@ -76,23 +78,23 @@ struct Shader { ShaderData *data = nullptr; String code; ShaderType type; - Map<StringName, Map<int, RID>> default_texture_parameter; - Set<Material *> owners; + HashMap<StringName, HashMap<int, RID>> default_texture_parameter; + HashSet<Material *> owners; }; /* Material structs */ struct MaterialData { - void update_uniform_buffer(const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Map<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color); - void update_textures(const Map<StringName, Variant> &p_parameters, const Map<StringName, Map<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color); + 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); virtual void set_render_priority(int p_priority) = 0; virtual void set_next_pass(RID p_pass) = 0; - virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0; + virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0; virtual ~MaterialData(); //to be used internally by update_parameters, in the most common configuration of material parameters - bool update_parameters_uniform_set(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const Map<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const Map<StringName, Map<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL); + 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, uint32_t p_barrier = RD::BARRIER_MASK_ALL); void free_parameters_uniform_set(RID p_uniform_set); private: @@ -101,7 +103,7 @@ private: List<RID>::Element *global_buffer_E = nullptr; List<RID>::Element *global_texture_E = nullptr; uint64_t global_textures_pass = 0; - Map<StringName, uint64_t> used_global_textures; + HashMap<StringName, uint64_t> used_global_textures; //internally by update_parameters_uniform_set Vector<uint8_t> ubo_data; @@ -120,12 +122,12 @@ struct Material { uint32_t shader_id = 0; bool uniform_dirty = false; bool texture_dirty = false; - Map<StringName, Variant> params; + HashMap<StringName, Variant> params; int32_t priority = 0; RID next_pass; SelfList<Material> update_element; - RendererStorage::Dependency dependency; + Dependency dependency; Material() : update_element(this) {} @@ -137,7 +139,7 @@ struct GlobalVariables { BUFFER_DIRTY_REGION_SIZE = 1024 }; struct Variable { - Set<RID> texture_materials; // materials using this + HashSet<RID> texture_materials; // materials using this RS::GlobalVariableType type; Variant value; @@ -232,6 +234,86 @@ public: MaterialStorage(); virtual ~MaterialStorage(); + /* Helpers */ + + static _FORCE_INLINE_ void store_transform(const Transform3D &p_mtx, float *p_array) { + p_array[0] = p_mtx.basis.rows[0][0]; + p_array[1] = p_mtx.basis.rows[1][0]; + p_array[2] = p_mtx.basis.rows[2][0]; + p_array[3] = 0; + p_array[4] = p_mtx.basis.rows[0][1]; + p_array[5] = p_mtx.basis.rows[1][1]; + p_array[6] = p_mtx.basis.rows[2][1]; + p_array[7] = 0; + p_array[8] = p_mtx.basis.rows[0][2]; + p_array[9] = p_mtx.basis.rows[1][2]; + p_array[10] = p_mtx.basis.rows[2][2]; + p_array[11] = 0; + p_array[12] = p_mtx.origin.x; + p_array[13] = p_mtx.origin.y; + p_array[14] = p_mtx.origin.z; + p_array[15] = 1; + } + + static _FORCE_INLINE_ void store_basis_3x4(const Basis &p_mtx, float *p_array) { + p_array[0] = p_mtx.rows[0][0]; + p_array[1] = p_mtx.rows[1][0]; + p_array[2] = p_mtx.rows[2][0]; + p_array[3] = 0; + p_array[4] = p_mtx.rows[0][1]; + p_array[5] = p_mtx.rows[1][1]; + p_array[6] = p_mtx.rows[2][1]; + p_array[7] = 0; + p_array[8] = p_mtx.rows[0][2]; + p_array[9] = p_mtx.rows[1][2]; + p_array[10] = p_mtx.rows[2][2]; + p_array[11] = 0; + } + + static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_mtx, float *p_array) { + p_array[0] = p_mtx.rows[0][0]; + p_array[1] = p_mtx.rows[1][0]; + p_array[2] = p_mtx.rows[2][0]; + p_array[3] = 0; + p_array[4] = p_mtx.rows[0][1]; + p_array[5] = p_mtx.rows[1][1]; + p_array[6] = p_mtx.rows[2][1]; + p_array[7] = 0; + p_array[8] = p_mtx.rows[0][2]; + p_array[9] = p_mtx.rows[1][2]; + p_array[10] = p_mtx.rows[2][2]; + p_array[11] = 0; + } + + static _FORCE_INLINE_ void store_transform_transposed_3x4(const Transform3D &p_mtx, float *p_array) { + p_array[0] = p_mtx.basis.rows[0][0]; + p_array[1] = p_mtx.basis.rows[0][1]; + p_array[2] = p_mtx.basis.rows[0][2]; + p_array[3] = p_mtx.origin.x; + p_array[4] = p_mtx.basis.rows[1][0]; + p_array[5] = p_mtx.basis.rows[1][1]; + p_array[6] = p_mtx.basis.rows[1][2]; + p_array[7] = p_mtx.origin.y; + p_array[8] = p_mtx.basis.rows[2][0]; + p_array[9] = p_mtx.basis.rows[2][1]; + p_array[10] = p_mtx.basis.rows[2][2]; + p_array[11] = p_mtx.origin.z; + } + + static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) { + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + p_array[i * 4 + j] = p_mtx.matrix[i][j]; + } + } + } + + static _FORCE_INLINE_ void store_soft_shadow_kernel(const float *p_kernel, float *p_array) { + for (int i = 0; i < 128; i++) { + p_array[i] = p_kernel[i]; + } + } + /* Samplers */ _FORCE_INLINE_ RID sampler_rd_get_default(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) { @@ -317,7 +399,7 @@ public: virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override; - virtual void material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) override; + virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) override; void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function); MaterialDataRequestFunction material_get_data_request_function(ShaderType p_shader_type); diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp index 9b7b0d2c25..3875eb6615 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp @@ -210,15 +210,17 @@ void MeshStorage::mesh_free(RID p_rid) { mesh_clear(p_rid); mesh_set_shadow_mesh(p_rid, RID()); Mesh *mesh = mesh_owner.get_or_null(p_rid); + ERR_FAIL_COND(!mesh); + mesh->dependency.deleted_notify(p_rid); if (mesh->instances.size()) { ERR_PRINT("deleting mesh with active instances"); } if (mesh->shadow_owners.size()) { - for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { - Mesh *shadow_owner = E->get(); + for (Mesh *E : mesh->shadow_owners) { + Mesh *shadow_owner = E; shadow_owner->shadow_mesh = RID(); - shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); + shadow_owner->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH); } } mesh_owner.free(p_rid); @@ -429,12 +431,12 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) _mesh_instance_add_surface(mi, mesh, mesh->surface_count - 1); } - mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); + mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH); - for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { - Mesh *shadow_owner = E->get(); + for (Mesh *E : mesh->shadow_owners) { + Mesh *shadow_owner = E; shadow_owner->shadow_mesh = RID(); - shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); + shadow_owner->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH); } mesh->material_cache.clear(); @@ -501,7 +503,7 @@ void MeshStorage::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_mat ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); mesh->surfaces[p_surface]->material = p_material; - mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL); + mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL); mesh->material_cache.clear(); } @@ -692,7 +694,7 @@ void MeshStorage::mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) { shadow_mesh->shadow_owners.insert(mesh); } - mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); + mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH); } void MeshStorage::mesh_clear(RID p_mesh) { @@ -740,12 +742,12 @@ void MeshStorage::mesh_clear(RID p_mesh) { _mesh_instance_clear(mi); } mesh->has_bone_weights = false; - mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); + mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH); - for (Set<Mesh *>::Element *E = mesh->shadow_owners.front(); E; E = E->next()) { - Mesh *shadow_owner = E->get(); + for (Mesh *E : mesh->shadow_owners) { + Mesh *shadow_owner = E; shadow_owner->shadow_mesh = RID(); - shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); + shadow_owner->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH); } } @@ -1209,7 +1211,7 @@ void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS:: multimesh->buffer = RD::get_singleton()->storage_buffer_create(multimesh->instances * multimesh->stride_cache * 4); } - multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MULTIMESH); + multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MULTIMESH); } int MeshStorage::multimesh_get_instance_count(RID p_multimesh) const { @@ -1243,7 +1245,7 @@ void MeshStorage::multimesh_set_mesh(RID p_multimesh, RID p_mesh) { } } - multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH); + multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH); } #define MULTIMESH_DIRTY_REGION_SIZE 512 @@ -1602,7 +1604,7 @@ void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_b const float *data = p_buffer.ptr(); _multimesh_re_create_aabb(multimesh, data, multimesh->instances); - multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB); + multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); } } @@ -1644,7 +1646,7 @@ void MeshStorage::multimesh_set_visible_instances(RID p_multimesh, int p_visible multimesh->visible_instances = p_visible; - multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES); + multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES); } int MeshStorage::multimesh_get_visible_instances(RID p_multimesh) const { @@ -1703,7 +1705,7 @@ void MeshStorage::_update_dirty_multimeshes() { //aabb is dirty.. _multimesh_re_create_aabb(multimesh, data, visible_instances); multimesh->aabb_dirty = false; - multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB); + multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); } } @@ -1781,7 +1783,7 @@ void MeshStorage::skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_ } } - skeleton->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA); + skeleton->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_SKELETON_DATA); } int MeshStorage::skeleton_get_bone_count(RID p_skeleton) const { @@ -1902,7 +1904,7 @@ void MeshStorage::_update_dirty_skeletons() { skeleton_dirty_list = skeleton->dirty_list; - skeleton->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_SKELETON_BONES); + skeleton->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_SKELETON_BONES); skeleton->version++; @@ -1913,7 +1915,7 @@ void MeshStorage::_update_dirty_skeletons() { skeleton_dirty_list = nullptr; } -void MeshStorage::skeleton_update_dependency(RID p_skeleton, RendererStorage::DependencyTracker *p_instance) { +void MeshStorage::skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance) { Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton); ERR_FAIL_COND(!skeleton); diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h index 7d3f603afd..9cdda6bfca 100644 --- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h @@ -35,8 +35,8 @@ #include "core/templates/rid_owner.h" #include "core/templates/self_list.h" #include "servers/rendering/renderer_rd/shaders/skeleton.glsl.gen.h" -#include "servers/rendering/renderer_storage.h" #include "servers/rendering/storage/mesh_storage.h" +#include "servers/rendering/storage/utilities.h" namespace RendererRD { @@ -141,9 +141,9 @@ struct Mesh { List<MeshInstance *> instances; RID shadow_mesh; - Set<Mesh *> shadow_owners; + HashSet<Mesh *> shadow_owners; - RendererStorage::Dependency dependency; + Dependency dependency; }; /* Mesh Instance */ @@ -199,7 +199,7 @@ struct MultiMesh { bool dirty = false; MultiMesh *dirty_list = nullptr; - RendererStorage::Dependency dependency; + Dependency dependency; }; /* Skeleton */ @@ -256,7 +256,7 @@ struct Skeleton { uint64_t version = 1; - RendererStorage::Dependency dependency; + Dependency dependency; }; class MeshStorage : public RendererMeshStorage { @@ -672,7 +672,7 @@ public: virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) override; virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const override; - virtual void skeleton_update_dependency(RID p_skeleton, RendererStorage::DependencyTracker *p_instance) override; + virtual void skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance) override; void _update_dirty_skeletons(); diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp index 094120f908..5200e0d318 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp @@ -30,7 +30,6 @@ #include "particles_storage.h" #include "servers/rendering/renderer_rd/renderer_compositor_rd.h" -#include "servers/rendering/renderer_rd/renderer_storage_rd.h" #include "servers/rendering/rendering_server_globals.h" #include "texture_storage.h" @@ -321,7 +320,7 @@ void ParticlesStorage::particles_set_amount(RID p_particles, int p_amount) { particles->prev_phase = 0; particles->clear = true; - particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES); + particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES); } void ParticlesStorage::particles_set_lifetime(RID p_particles, double p_lifetime) { @@ -356,7 +355,7 @@ void ParticlesStorage::particles_set_custom_aabb(RID p_particles, const AABB &p_ Particles *particles = particles_owner.get_or_null(p_particles); ERR_FAIL_COND(!particles); particles->custom_aabb = p_aabb; - particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB); + particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); } void ParticlesStorage::particles_set_speed_scale(RID p_particles, double p_scale) { @@ -370,7 +369,7 @@ void ParticlesStorage::particles_set_use_local_coordinates(RID p_particles, bool ERR_FAIL_COND(!particles); particles->use_local_coords = p_enable; - particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES); + particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES); } void ParticlesStorage::particles_set_fixed_fps(RID p_particles, int p_fps) { @@ -386,7 +385,7 @@ void ParticlesStorage::particles_set_fixed_fps(RID p_particles, int p_fps) { particles->prev_phase = 0; particles->clear = true; - particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES); + particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES); } void ParticlesStorage::particles_set_interpolate(RID p_particles, bool p_enable) { @@ -419,7 +418,7 @@ void ParticlesStorage::particles_set_trails(RID p_particles, bool p_enable, doub particles->prev_phase = 0; particles->clear = true; - particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES); + particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES); } void ParticlesStorage::particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) { @@ -436,7 +435,7 @@ void ParticlesStorage::particles_set_trail_bind_poses(RID p_particles, const Vec particles->trail_bind_poses = p_bind_poses; particles->trail_bind_poses_dirty = true; - particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES); + particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES); } void ParticlesStorage::particles_set_collision_base_size(RID p_particles, real_t p_size) { @@ -458,7 +457,7 @@ void ParticlesStorage::particles_set_process_material(RID p_particles, RID p_mat ERR_FAIL_COND(!particles); particles->process_material = p_material; - particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES); //the instance buffer may have changed + particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES); //the instance buffer may have changed } RID ParticlesStorage::particles_get_process_material(RID p_particles) const { @@ -540,15 +539,12 @@ void ParticlesStorage::particles_emit(RID p_particles, const Transform3D &p_tran _particles_allocate_emission_buffer(particles); } - if (particles->inactive) { - //in case it was inactive, make active again - particles->inactive = false; - particles->inactive_time = 0; - } + particles->inactive = false; + particles->inactive_time = 0; int32_t idx = particles->emission_buffer->particle_count; if (idx < particles->emission_buffer->particle_max) { - RendererStorageRD::store_transform(p_transform, particles->emission_buffer->data[idx].xform); + RendererRD::MaterialStorage::store_transform(p_transform, particles->emission_buffer->data[idx].xform); particles->emission_buffer->data[idx].velocity[0] = p_velocity.x; particles->emission_buffer->data[idx].velocity[1] = p_velocity.y; @@ -769,9 +765,9 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta frame_params.randomness = p_particles->randomness; if (p_particles->use_local_coords) { - RendererStorageRD::store_transform(Transform3D(), frame_params.emission_transform); + RendererRD::MaterialStorage::store_transform(Transform3D(), frame_params.emission_transform); } else { - RendererStorageRD::store_transform(p_particles->emission_transform, frame_params.emission_transform); + RendererRD::MaterialStorage::store_transform(p_particles->emission_transform, frame_params.emission_transform); } frame_params.cycle = p_particles->cycle_number; @@ -838,8 +834,8 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta } uint32_t collision_3d_textures_used = 0; - for (const Set<RID>::Element *E = p_particles->collisions.front(); E; E = E->next()) { - ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(E->get()); + for (const RID &E : p_particles->collisions) { + ParticlesCollisionInstance *pci = particles_collision_instance_owner.get_or_null(E); if (!pci || !pci->active) { continue; } @@ -861,7 +857,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta ParticlesFrameParams::Attractor &attr = frame_params.attractors[frame_params.attractor_count]; - RendererStorageRD::store_transform(to_collider, attr.transform); + RendererRD::MaterialStorage::store_transform(to_collider, attr.transform); attr.strength = pc->attractor_strength; attr.attenuation = pc->attractor_attenuation; attr.directionality = pc->attractor_directionality; @@ -909,7 +905,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta ParticlesFrameParams::Collider &col = frame_params.colliders[frame_params.collider_count]; - RendererStorageRD::store_transform(to_collider, col.transform); + RendererRD::MaterialStorage::store_transform(to_collider, col.transform); switch (pc->type) { case RS::PARTICLES_COLLISION_TYPE_SPHERE_COLLIDE: { col.type = ParticlesFrameParams::COLLISION_TYPE_SPHERE; @@ -1206,7 +1202,7 @@ void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p RD::get_singleton()->compute_list_dispatch_threads(compute_list, particles->amount, 1, 1); RD::get_singleton()->compute_list_end(); - RendererStorageRD::base_singleton->get_effects()->sort_buffer(particles->particles_sort_uniform_set, particles->amount); + RendererCompositorRD::singleton->get_effects()->sort_buffer(particles->particles_sort_uniform_set, particles->amount); } copy_push_constant.total_particles *= copy_push_constant.total_particles; @@ -1386,7 +1382,7 @@ void ParticlesStorage::update_particles() { } for (int i = 0; i < particles->trail_bind_poses.size(); i++) { - RendererStorageRD::store_transform(particles->trail_bind_poses[i], &particles_shader.pose_update_buffer[i * 16]); + RendererRD::MaterialStorage::store_transform(particles->trail_bind_poses[i], &particles_shader.pose_update_buffer[i * 16]); } RD::get_singleton()->buffer_update(particles->trail_bind_pose_buffer, 0, particles->trail_bind_poses.size() * 16 * sizeof(float), particles_shader.pose_update_buffer.ptr()); @@ -1460,14 +1456,14 @@ void ParticlesStorage::update_particles() { // In local mode, particle positions are calculated locally (relative to the node position) // and they're also drawn locally. // It works as expected, so we just pass an identity transform. - RendererStorageRD::store_transform(Transform3D(), copy_push_constant.inv_emission_transform); + RendererRD::MaterialStorage::store_transform(Transform3D(), copy_push_constant.inv_emission_transform); } else { // In global mode, particle positions are calculated globally (relative to the canvas origin) // but they're drawn locally. // So, we need to pass the inverse of the emission transform to bring the // particles to local coordinates before drawing. Transform3D inv = particles->emission_transform.affine_inverse(); - RendererStorageRD::store_transform(inv, copy_push_constant.inv_emission_transform); + RendererRD::MaterialStorage::store_transform(inv, copy_push_constant.inv_emission_transform); } copy_push_constant.total_particles = total_amount; @@ -1503,7 +1499,7 @@ void ParticlesStorage::update_particles() { RD::get_singleton()->compute_list_end(); } - particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB); + particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); } } @@ -1592,14 +1588,14 @@ void ParticlesStorage::ParticlesShaderData::set_default_texture_param(const Stri } } else { if (!default_texture_params.has(p_name)) { - default_texture_params[p_name] = Map<int, RID>(); + default_texture_params[p_name] = HashMap<int, RID>(); } default_texture_params[p_name][p_index] = p_texture; } } void ParticlesStorage::ParticlesShaderData::get_param_list(List<PropertyInfo> *p_param_list) const { - Map<int, StringName> order; + HashMap<int, StringName> order; for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) { if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) { @@ -1676,7 +1672,7 @@ ShaderData *ParticlesStorage::_create_particles_shader_func() { return shader_data; } -bool ParticlesStorage::ParticlesMaterialData::update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +bool ParticlesStorage::ParticlesMaterialData::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); } @@ -1759,7 +1755,7 @@ void ParticlesStorage::particles_collision_set_collision_type(RID p_particles_co particles_collision->heightfield_texture = RID(); } particles_collision->type = p_type; - particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB); + particles_collision->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); } void ParticlesStorage::particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) { @@ -1773,7 +1769,7 @@ void ParticlesStorage::particles_collision_set_sphere_radius(RID p_particles_col ERR_FAIL_COND(!particles_collision); particles_collision->radius = p_radius; - particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB); + particles_collision->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); } void ParticlesStorage::particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) { @@ -1781,7 +1777,7 @@ void ParticlesStorage::particles_collision_set_box_extents(RID p_particles_colli ERR_FAIL_COND(!particles_collision); particles_collision->extents = p_extents; - particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB); + particles_collision->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); } void ParticlesStorage::particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) { @@ -1815,7 +1811,7 @@ void ParticlesStorage::particles_collision_set_field_texture(RID p_particles_col void ParticlesStorage::particles_collision_height_field_update(RID p_particles_collision) { ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision); ERR_FAIL_COND(!particles_collision); - particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB); + particles_collision->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); } void ParticlesStorage::particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) { diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h index c6480794c1..70ac6f0349 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h @@ -37,9 +37,9 @@ #include "servers/rendering/renderer_rd/shaders/particles.glsl.gen.h" #include "servers/rendering/renderer_rd/shaders/particles_copy.glsl.gen.h" #include "servers/rendering/renderer_rd/storage_rd/material_storage.h" -#include "servers/rendering/renderer_storage.h" #include "servers/rendering/shader_compiler.h" #include "servers/rendering/storage/particles_storage.h" +#include "servers/rendering/storage/utilities.h" namespace RendererRD { @@ -224,9 +224,9 @@ struct Particles { ParticleEmissionBuffer *emission_buffer = nullptr; RID emission_storage_buffer; - Set<RID> collisions; + HashSet<RID> collisions; - RendererStorage::Dependency dependency; + Dependency dependency; double trail_length = 1.0; bool trails_enabled = false; @@ -254,7 +254,7 @@ struct ParticlesCollision { RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024; - RendererStorage::Dependency dependency; + Dependency dependency; }; struct ParticlesCollisionInstance { @@ -345,7 +345,7 @@ private: RID version; bool uses_collision = false; - Map<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; + HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms; Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms; Vector<uint32_t> ubo_offsets; @@ -353,7 +353,7 @@ private: String path; String code; - Map<StringName, Map<int, RID>> default_texture_params; + HashMap<StringName, HashMap<int, RID>> default_texture_params; RID pipeline; @@ -387,7 +387,7 @@ private: virtual void set_render_priority(int p_priority) {} virtual void set_next_pass(RID p_pass) {} - virtual bool update_parameters(const Map<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); + virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); virtual ~ParticlesMaterialData(); }; diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index 7d4808f936..abf364b8b4 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -191,7 +191,7 @@ TextureStorage::TextureStorage() { } } - { //create default cubemap + { //create default black cubemap array RD::TextureFormat tformat; tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; @@ -219,7 +219,35 @@ TextureStorage::TextureStorage() { } } - { //create default cubemap array + { //create default white cubemap array + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.array_layers = 6; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY; + + Vector<uint8_t> pv; + pv.resize(16 * 4); + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 255); + pv.set(i * 4 + 1, 255); + pv.set(i * 4 + 2, 255); + pv.set(i * 4 + 3, 255); + } + + { + Vector<Vector<uint8_t>> vpv; + for (int i = 0; i < 6; i++) { + vpv.push_back(pv); + } + default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } + + { //create default black cubemap RD::TextureFormat tformat; tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; @@ -247,7 +275,7 @@ TextureStorage::TextureStorage() { } } - { //create default cubemap white array + { //create default white cubemap RD::TextureFormat tformat; tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; @@ -349,7 +377,6 @@ TextureStorage::TextureStorage() { Vector<uint8_t> pv; pv.resize(16 * 4); - for (int i = 0; i < 16; i++) { pv.set(i * 4 + 0, 0); pv.set(i * 4 + 1, 0); @@ -358,7 +385,6 @@ TextureStorage::TextureStorage() { } { - //take the chance and initialize decal atlas to something Vector<Vector<uint8_t>> vpv; vpv.push_back(pv); decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); @@ -366,6 +392,29 @@ TextureStorage::TextureStorage() { } } + { //create default VRS + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8_UINT; + tformat.width = 4; + tformat.height = 4; + tformat.array_layers = 1; + tformat.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.texture_type = RD::TEXTURE_TYPE_2D_ARRAY; + + Vector<uint8_t> pv; + pv.resize(4 * 4); + for (int i = 0; i < 4 * 4; i++) { + pv.set(i, 0); + } + + { + Vector<Vector<uint8_t>> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_VRS] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } + { Vector<String> sdf_modes; sdf_modes.push_back("\n#define MODE_LOAD\n"); @@ -1712,7 +1761,7 @@ void TextureStorage::decal_set_extents(RID p_decal, const Vector3 &p_extents) { Decal *decal = decal_owner.get_or_null(p_decal); ERR_FAIL_COND(!decal); decal->extents = p_extents; - decal->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB); + decal->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); } void TextureStorage::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) { @@ -1736,7 +1785,7 @@ void TextureStorage::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID texture_add_to_decal_atlas(decal->textures[p_type]); } - decal->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_DECAL); + decal->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_DECAL); } void TextureStorage::decal_set_emission_energy(RID p_decal, float p_energy) { @@ -1761,7 +1810,7 @@ void TextureStorage::decal_set_cull_mask(RID p_decal, uint32_t p_layers) { Decal *decal = decal_owner.get_or_null(p_decal); ERR_FAIL_COND(!decal); decal->cull_mask = p_layers; - decal->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB); + decal->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); } void TextureStorage::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) { @@ -2075,7 +2124,7 @@ void TextureStorage::_update_render_target(RenderTarget *rt) { //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->flags[RENDER_TARGET_TRANSPARENT] ? Image::FORMAT_RGBA8 : Image::FORMAT_RGB8; + rt->image_format = rt->is_transparent ? Image::FORMAT_RGBA8 : Image::FORMAT_RGB8; RD::TextureFormat rd_format; RD::TextureView rd_view; @@ -2127,7 +2176,7 @@ void TextureStorage::_update_render_target(RenderTarget *rt) { //so transparent can be supported RD::TextureView view; view.format_override = rt->color_format; - if (!rt->flags[RENDER_TARGET_TRANSPARENT]) { + if (!rt->is_transparent) { view.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; } tex->rd_texture = RD::get_singleton()->texture_create_shared(view, rt->color); @@ -2194,9 +2243,6 @@ RID TextureStorage::render_target_create() { render_target.was_used = false; render_target.clear_requested = false; - for (int i = 0; i < RENDER_TARGET_FLAG_MAX; i++) { - render_target.flags[i] = false; - } _update_render_target(&render_target); return render_target_owner.make_rid(render_target); } @@ -2240,13 +2286,16 @@ RID TextureStorage::render_target_get_texture(RID p_render_target) { void TextureStorage::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) { } -void TextureStorage::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) { +void TextureStorage::render_target_set_transparent(RID p_render_target, bool p_is_transparent) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND(!rt); - rt->flags[p_flag] = p_value; + rt->is_transparent = p_is_transparent; _update_render_target(rt); } +void TextureStorage::render_target_set_direct_to_screen(RID p_render_target, bool p_value) { +} + bool TextureStorage::render_target_was_used(RID p_render_target) { RenderTarget *rt = render_target_owner.get_or_null(p_render_target); ERR_FAIL_COND_V(!rt, false); @@ -2751,3 +2800,31 @@ void TextureStorage::render_target_set_backbuffer_uniform_set(RID p_render_targe ERR_FAIL_COND(!rt); rt->backbuffer_uniform_set = p_uniform_set; } + +void TextureStorage::render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND(!rt); + + rt->vrs_mode = p_mode; +} + +void TextureStorage::render_target_set_vrs_texture(RID p_render_target, RID p_texture) { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND(!rt); + + rt->vrs_texture = p_texture; +} + +RS::ViewportVRSMode TextureStorage::render_target_get_vrs_mode(RID p_render_target) const { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND_V(!rt, RS::VIEWPORT_VRS_DISABLED); + + return rt->vrs_mode; +} + +RID TextureStorage::render_target_get_vrs_texture(RID p_render_target) const { + RenderTarget *rt = render_target_owner.get_or_null(p_render_target); + ERR_FAIL_COND_V(!rt, RID()); + + return rt->vrs_texture; +} diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h index a6f50803e4..8807f78f6e 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h @@ -33,8 +33,8 @@ #include "core/templates/rid_owner.h" #include "servers/rendering/renderer_rd/shaders/canvas_sdf.glsl.gen.h" -#include "servers/rendering/renderer_storage.h" #include "servers/rendering/storage/texture_storage.h" +#include "servers/rendering/storage/utilities.h" namespace RendererRD { @@ -48,10 +48,12 @@ enum DefaultRDTexture { DEFAULT_RD_TEXTURE_CUBEMAP_BLACK, DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK, DEFAULT_RD_TEXTURE_CUBEMAP_WHITE, + DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_WHITE, DEFAULT_RD_TEXTURE_3D_WHITE, DEFAULT_RD_TEXTURE_3D_BLACK, DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE, DEFAULT_RD_TEXTURE_2D_UINT, + DEFAULT_RD_TEXTURE_VRS, DEFAULT_RD_TEXTURE_MAX }; @@ -124,7 +126,7 @@ public: RID proxy_to; Vector<RID> proxies; - Set<RID> lightmap_users; + HashSet<RID> lightmap_users; RS::TextureDetectCallback detect_3d_callback = nullptr; void *detect_3d_callback_ud = nullptr; @@ -193,7 +195,7 @@ struct Decal { float distance_fade_length = 1; float normal_fade = 0.0; - RendererStorage::Dependency dependency; + Dependency dependency; }; struct RenderTarget { @@ -207,7 +209,7 @@ struct RenderTarget { RD::DataFormat color_format_srgb = RD::DATA_FORMAT_R4G4_UNORM_PACK8; Image::Format image_format = Image::FORMAT_L8; - bool flags[RendererTextureStorage::RENDER_TARGET_FLAG_MAX]; + bool is_transparent = false; bool sdf_enabled = false; @@ -229,6 +231,10 @@ struct RenderTarget { RS::ViewportSDFScale sdf_scale = RS::VIEWPORT_SDF_SCALE_50_PERCENT; Size2i process_size; + // VRS + RS::ViewportVRSMode vrs_mode = RS::VIEWPORT_VRS_DISABLED; + RID vrs_texture; + //texture generated for this owner (nor RD). RID texture; bool was_used; @@ -525,7 +531,8 @@ public: virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override; virtual RID render_target_get_texture(RID p_render_target) override; virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override; - virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) override; + virtual void render_target_set_transparent(RID p_render_target, bool p_is_transparent) override; + virtual void render_target_set_direct_to_screen(RID p_render_target, bool p_direct_to_screen) override; virtual bool render_target_was_used(RID p_render_target) override; virtual void render_target_set_as_unused(RID p_render_target) override; @@ -548,6 +555,12 @@ public: virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override; bool render_target_is_sdf_enabled(RID p_render_target) const; + virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override; + virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override; + + RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const; + RID render_target_get_vrs_texture(RID p_render_target) const; + Size2 render_target_get_size(RID p_render_target); RID render_target_get_rd_framebuffer(RID p_render_target); RID render_target_get_rd_texture(RID p_render_target); diff --git a/servers/rendering/renderer_rd/storage_rd/utilities.cpp b/servers/rendering/renderer_rd/storage_rd/utilities.cpp new file mode 100644 index 0000000000..a1f62c16c7 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/utilities.cpp @@ -0,0 +1,337 @@ +/*************************************************************************/ +/* utilities.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "utilities.h" +#include "../environment/fog.h" +#include "../environment/gi.h" +#include "light_storage.h" +#include "mesh_storage.h" +#include "particles_storage.h" +#include "texture_storage.h" + +using namespace RendererRD; + +Utilities *Utilities::singleton = nullptr; + +Utilities::Utilities() { + singleton = this; +} + +Utilities::~Utilities() { + singleton = nullptr; +} + +/* INSTANCES */ + +RS::InstanceType Utilities::get_base_type(RID p_rid) const { + if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_rid)) { + return RS::INSTANCE_MESH; + } + if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_rid)) { + return RS::INSTANCE_MULTIMESH; + } + if (RendererRD::LightStorage::get_singleton()->owns_reflection_probe(p_rid)) { + return RS::INSTANCE_REFLECTION_PROBE; + } + if (RendererRD::TextureStorage::get_singleton()->owns_decal(p_rid)) { + return RS::INSTANCE_DECAL; + } + if (RendererRD::GI::get_singleton()->owns_voxel_gi(p_rid)) { + return RS::INSTANCE_VOXEL_GI; + } + if (RendererRD::LightStorage::get_singleton()->owns_light(p_rid)) { + return RS::INSTANCE_LIGHT; + } + if (RendererRD::LightStorage::get_singleton()->owns_lightmap(p_rid)) { + return RS::INSTANCE_LIGHTMAP; + } + if (RendererRD::ParticlesStorage::get_singleton()->owns_particles(p_rid)) { + return RS::INSTANCE_PARTICLES; + } + if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision(p_rid)) { + return RS::INSTANCE_PARTICLES_COLLISION; + } + if (RendererRD::Fog::get_singleton()->owns_fog_volume(p_rid)) { + return RS::INSTANCE_FOG_VOLUME; + } + if (owns_visibility_notifier(p_rid)) { + return RS::INSTANCE_VISIBLITY_NOTIFIER; + } + + return RS::INSTANCE_NONE; +} + +bool Utilities::free(RID p_rid) { + if (RendererRD::TextureStorage::get_singleton()->owns_texture(p_rid)) { + RendererRD::TextureStorage::get_singleton()->texture_free(p_rid); + } else if (RendererRD::TextureStorage::get_singleton()->owns_canvas_texture(p_rid)) { + RendererRD::TextureStorage::get_singleton()->canvas_texture_free(p_rid); + } else if (RendererRD::MaterialStorage::get_singleton()->owns_shader(p_rid)) { + RendererRD::MaterialStorage::get_singleton()->shader_free(p_rid); + } else if (RendererRD::MaterialStorage::get_singleton()->owns_material(p_rid)) { + RendererRD::MaterialStorage::get_singleton()->material_free(p_rid); + } else if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_rid)) { + RendererRD::MeshStorage::get_singleton()->mesh_free(p_rid); + } else if (RendererRD::MeshStorage::get_singleton()->owns_mesh_instance(p_rid)) { + RendererRD::MeshStorage::get_singleton()->mesh_instance_free(p_rid); + } else if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_rid)) { + RendererRD::MeshStorage::get_singleton()->multimesh_free(p_rid); + } else if (RendererRD::MeshStorage::get_singleton()->owns_skeleton(p_rid)) { + RendererRD::MeshStorage::get_singleton()->skeleton_free(p_rid); + } else if (RendererRD::LightStorage::get_singleton()->owns_reflection_probe(p_rid)) { + RendererRD::LightStorage::get_singleton()->reflection_probe_free(p_rid); + } else if (RendererRD::TextureStorage::get_singleton()->owns_decal(p_rid)) { + RendererRD::TextureStorage::get_singleton()->decal_free(p_rid); + } else if (RendererRD::GI::get_singleton()->owns_voxel_gi(p_rid)) { + RendererRD::GI::get_singleton()->voxel_gi_free(p_rid); + } else if (RendererRD::LightStorage::get_singleton()->owns_lightmap(p_rid)) { + RendererRD::LightStorage::get_singleton()->lightmap_free(p_rid); + } else if (RendererRD::LightStorage::get_singleton()->owns_light(p_rid)) { + RendererRD::LightStorage::get_singleton()->light_free(p_rid); + } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles(p_rid)) { + RendererRD::ParticlesStorage::get_singleton()->particles_free(p_rid); + } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision(p_rid)) { + RendererRD::ParticlesStorage::get_singleton()->particles_collision_free(p_rid); + } else if (owns_visibility_notifier(p_rid)) { + visibility_notifier_free(p_rid); + } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision_instance(p_rid)) { + RendererRD::ParticlesStorage::get_singleton()->particles_collision_instance_free(p_rid); + } else if (RendererRD::Fog::get_singleton()->owns_fog_volume(p_rid)) { + RendererRD::Fog::get_singleton()->fog_free(p_rid); + } else if (RendererRD::TextureStorage::get_singleton()->owns_render_target(p_rid)) { + RendererRD::TextureStorage::get_singleton()->render_target_free(p_rid); + } else { + return false; + } + + return true; +} + +/* DEPENDENCIES */ + +void Utilities::base_update_dependency(RID p_base, DependencyTracker *p_instance) { + if (MeshStorage::get_singleton()->owns_mesh(p_base)) { + Mesh *mesh = MeshStorage::get_singleton()->get_mesh(p_base); + p_instance->update_dependency(&mesh->dependency); + } else if (MeshStorage::get_singleton()->owns_multimesh(p_base)) { + MultiMesh *multimesh = MeshStorage::get_singleton()->get_multimesh(p_base); + p_instance->update_dependency(&multimesh->dependency); + if (multimesh->mesh.is_valid()) { + base_update_dependency(multimesh->mesh, p_instance); + } + } else if (LightStorage::get_singleton()->owns_reflection_probe(p_base)) { + ReflectionProbe *rp = LightStorage::get_singleton()->get_reflection_probe(p_base); + p_instance->update_dependency(&rp->dependency); + } else if (TextureStorage::get_singleton()->owns_decal(p_base)) { + Decal *decal = TextureStorage::get_singleton()->get_decal(p_base); + p_instance->update_dependency(&decal->dependency); + } else if (GI::get_singleton()->owns_voxel_gi(p_base)) { + GI::VoxelGI *gip = GI::get_singleton()->get_voxel_gi(p_base); + p_instance->update_dependency(&gip->dependency); + } else if (LightStorage::get_singleton()->owns_lightmap(p_base)) { + Lightmap *lm = LightStorage::get_singleton()->get_lightmap(p_base); + p_instance->update_dependency(&lm->dependency); + } else if (LightStorage::get_singleton()->owns_light(p_base)) { + Light *l = LightStorage::get_singleton()->get_light(p_base); + p_instance->update_dependency(&l->dependency); + } else if (ParticlesStorage::get_singleton()->owns_particles(p_base)) { + Particles *p = ParticlesStorage::get_singleton()->get_particles(p_base); + p_instance->update_dependency(&p->dependency); + } else if (ParticlesStorage::get_singleton()->owns_particles_collision(p_base)) { + ParticlesCollision *pc = ParticlesStorage::get_singleton()->get_particles_collision(p_base); + p_instance->update_dependency(&pc->dependency); + } else if (Fog::get_singleton()->owns_fog_volume(p_base)) { + Fog::FogVolume *fv = Fog::get_singleton()->get_fog_volume(p_base); + p_instance->update_dependency(&fv->dependency); + } else if (owns_visibility_notifier(p_base)) { + VisibilityNotifier *vn = get_visibility_notifier(p_base); + p_instance->update_dependency(&vn->dependency); + } +} + +/* VISIBILITY NOTIFIER */ + +RID Utilities::visibility_notifier_allocate() { + return visibility_notifier_owner.allocate_rid(); +} + +void Utilities::visibility_notifier_initialize(RID p_notifier) { + visibility_notifier_owner.initialize_rid(p_notifier, VisibilityNotifier()); +} + +void Utilities::visibility_notifier_free(RID p_notifier) { + VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier); + vn->dependency.deleted_notify(p_notifier); + visibility_notifier_owner.free(p_notifier); +} + +void Utilities::visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) { + VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier); + ERR_FAIL_COND(!vn); + vn->aabb = p_aabb; + vn->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB); +} + +void Utilities::visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) { + VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier); + ERR_FAIL_COND(!vn); + vn->enter_callback = p_enter_callbable; + vn->exit_callback = p_exit_callable; +} + +AABB Utilities::visibility_notifier_get_aabb(RID p_notifier) const { + const VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier); + ERR_FAIL_COND_V(!vn, AABB()); + return vn->aabb; +} + +void Utilities::visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) { + VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier); + ERR_FAIL_COND(!vn); + + if (p_enter) { + if (!vn->enter_callback.is_null()) { + if (p_deferred) { + vn->enter_callback.call_deferred(nullptr, 0); + } else { + Variant r; + Callable::CallError ce; + vn->enter_callback.call(nullptr, 0, r, ce); + } + } + } else { + if (!vn->exit_callback.is_null()) { + if (p_deferred) { + vn->exit_callback.call_deferred(nullptr, 0); + } else { + Variant r; + Callable::CallError ce; + vn->exit_callback.call(nullptr, 0, r, ce); + } + } + } +} + +/* TIMING */ + +void Utilities::capture_timestamps_begin() { + RD::get_singleton()->capture_timestamp("Frame Begin"); +} + +void Utilities::capture_timestamp(const String &p_name) { + RD::get_singleton()->capture_timestamp(p_name); +} + +uint32_t Utilities::get_captured_timestamps_count() const { + return RD::get_singleton()->get_captured_timestamps_count(); +} + +uint64_t Utilities::get_captured_timestamps_frame() const { + return RD::get_singleton()->get_captured_timestamps_frame(); +} + +uint64_t Utilities::get_captured_timestamp_gpu_time(uint32_t p_index) const { + return RD::get_singleton()->get_captured_timestamp_gpu_time(p_index); +} + +uint64_t Utilities::get_captured_timestamp_cpu_time(uint32_t p_index) const { + return RD::get_singleton()->get_captured_timestamp_cpu_time(p_index); +} + +String Utilities::get_captured_timestamp_name(uint32_t p_index) const { + return RD::get_singleton()->get_captured_timestamp_name(p_index); +} + +/* MISC */ + +void Utilities::update_dirty_resources() { + MaterialStorage::get_singleton()->_update_global_variables(); //must do before materials, so it can queue them for update + MaterialStorage::get_singleton()->_update_queued_materials(); + MeshStorage::get_singleton()->_update_dirty_multimeshes(); + MeshStorage::get_singleton()->_update_dirty_skeletons(); + TextureStorage::get_singleton()->update_decal_atlas(); +} + +bool Utilities::has_os_feature(const String &p_feature) const { + if (!RD::get_singleton()) { + return false; + } + + if (p_feature == "rgtc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC5_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) { + return true; + } + + if (p_feature == "s3tc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) { + return true; + } + + if (p_feature == "bptc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC7_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) { + return true; + } + + if ((p_feature == "etc" || p_feature == "etc2") && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) { + return true; + } + + return false; +} + +void Utilities::update_memory_info() { + texture_mem_cache = RenderingDevice::get_singleton()->get_memory_usage(RenderingDevice::MEMORY_TEXTURES); + buffer_mem_cache = RenderingDevice::get_singleton()->get_memory_usage(RenderingDevice::MEMORY_BUFFERS); + total_mem_cache = RenderingDevice::get_singleton()->get_memory_usage(RenderingDevice::MEMORY_TOTAL); +} + +uint64_t Utilities::get_rendering_info(RS::RenderingInfo p_info) { + if (p_info == RS::RENDERING_INFO_TEXTURE_MEM_USED) { + return texture_mem_cache; + } else if (p_info == RS::RENDERING_INFO_BUFFER_MEM_USED) { + return buffer_mem_cache; + } else if (p_info == RS::RENDERING_INFO_VIDEO_MEM_USED) { + return total_mem_cache; + } + return 0; +} + +String Utilities::get_video_adapter_name() const { + return RenderingDevice::get_singleton()->get_device_name(); +} + +String Utilities::get_video_adapter_vendor() const { + return RenderingDevice::get_singleton()->get_device_vendor_name(); +} + +RenderingDevice::DeviceType Utilities::get_video_adapter_type() const { + return RenderingDevice::get_singleton()->get_device_type(); +} + +String Utilities::get_video_adapter_api_version() const { + return RenderingDevice::get_singleton()->get_device_api_version(); +} diff --git a/servers/rendering/renderer_rd/storage_rd/utilities.h b/servers/rendering/renderer_rd/storage_rd/utilities.h new file mode 100644 index 0000000000..979e984546 --- /dev/null +++ b/servers/rendering/renderer_rd/storage_rd/utilities.h @@ -0,0 +1,122 @@ +/*************************************************************************/ +/* utilities.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef UTILITIES_RD_H +#define UTILITIES_RD_H + +#include "core/templates/rid_owner.h" +#include "servers/rendering/storage/utilities.h" + +namespace RendererRD { + +/* VISIBILITY NOTIFIER */ + +struct VisibilityNotifier { + AABB aabb; + Callable enter_callback; + Callable exit_callback; + Dependency dependency; +}; + +class Utilities : public RendererUtilities { +private: + static Utilities *singleton; + + /* VISIBILITY NOTIFIER */ + + mutable RID_Owner<VisibilityNotifier> visibility_notifier_owner; + + /* MISC */ + + //keep cached since it can be called form any thread + uint64_t texture_mem_cache = 0; + uint64_t buffer_mem_cache = 0; + uint64_t total_mem_cache = 0; + +public: + static Utilities *get_singleton() { return singleton; } + + Utilities(); + virtual ~Utilities() override; + + /* INSTANCES */ + + virtual RS::InstanceType get_base_type(RID p_rid) const override; + virtual bool free(RID p_rid) override; + + /* DEPENDENCIES */ + + virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) override; + + /* VISIBILITY NOTIFIER */ + + VisibilityNotifier *get_visibility_notifier(RID p_rid) { return visibility_notifier_owner.get_or_null(p_rid); }; + bool owns_visibility_notifier(RID p_rid) const { return visibility_notifier_owner.owns(p_rid); }; + + virtual RID visibility_notifier_allocate() override; + virtual void visibility_notifier_initialize(RID p_notifier) override; + virtual void visibility_notifier_free(RID p_notifier) override; + + virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) override; + virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) override; + + virtual AABB visibility_notifier_get_aabb(RID p_notifier) const override; + virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) override; + + /* TIMING */ + + virtual void capture_timestamps_begin() override; + virtual void capture_timestamp(const String &p_name) override; + virtual uint32_t get_captured_timestamps_count() const override; + virtual uint64_t get_captured_timestamps_frame() const override; + virtual uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const override; + virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const override; + virtual String get_captured_timestamp_name(uint32_t p_index) const override; + + /* MISC */ + + virtual void update_dirty_resources() override; + virtual void set_debug_generate_wireframes(bool p_generate) override {} + + virtual bool has_os_feature(const String &p_feature) const override; + + virtual void update_memory_info() override; + + virtual uint64_t get_rendering_info(RS::RenderingInfo p_info) override; + + virtual String get_video_adapter_name() const override; + virtual String get_video_adapter_vendor() const override; + virtual RenderingDevice::DeviceType get_video_adapter_type() const override; + virtual String get_video_adapter_api_version() const override; +}; + +} // namespace RendererRD + +#endif // !UTILITIES_RD_H diff --git a/servers/rendering/renderer_rd/uniform_set_cache_rd.h b/servers/rendering/renderer_rd/uniform_set_cache_rd.h index e49cf4dafa..af22a48716 100644 --- a/servers/rendering/renderer_rd/uniform_set_cache_rd.h +++ b/servers/rendering/renderer_rd/uniform_set_cache_rd.h @@ -57,13 +57,13 @@ class UniformSetCacheRD : public Object { Cache *hash_table[HASH_TABLE_SIZE] = {}; static _FORCE_INLINE_ uint32_t _hash_uniform(const RD::Uniform &u, uint32_t h) { - h = hash_djb2_one_32(u.uniform_type, h); - h = hash_djb2_one_32(u.binding, h); + h = hash_murmur3_one_32(u.uniform_type, h); + h = hash_murmur3_one_32(u.binding, h); uint32_t rsize = u.get_id_count(); for (uint32_t j = 0; j < rsize; j++) { - h = hash_djb2_one_64(u.get_id(j).get_id(), h); + h = hash_murmur3_one_64(u.get_id(j).get_id(), h); } - return h; + return hash_fmix32(h); } static _FORCE_INLINE_ bool _compare_uniform(const RD::Uniform &a, const RD::Uniform &b) { @@ -154,8 +154,8 @@ class UniformSetCacheRD : public Object { public: template <typename... Args> RID get_cache(RID p_shader, uint32_t p_set, Args... args) { - uint32_t h = hash_djb2_one_64(p_shader.get_id()); - h = hash_djb2_one_32(p_set, h); + uint32_t h = hash_murmur3_one_64(p_shader.get_id()); + h = hash_murmur3_one_32(p_set, h); h = _hash_args(h, args...); uint32_t table_idx = h % HASH_TABLE_SIZE; @@ -180,12 +180,14 @@ public: template <typename... Args> RID get_cache_vec(RID p_shader, uint32_t p_set, const Vector<RD::Uniform> &p_uniforms) { - uint32_t h = hash_djb2_one_64(p_shader.get_id()); - h = hash_djb2_one_32(p_set, h); + uint32_t h = hash_murmur3_one_64(p_shader.get_id()); + h = hash_murmur3_one_32(p_set, h); for (int i = 0; i < p_uniforms.size(); i++) { h = _hash_uniform(p_uniforms[i], h); } + h = hash_fmix32(h); + uint32_t table_idx = h % HASH_TABLE_SIZE; { const Cache *c = hash_table[table_idx]; |