diff options
author | Bastiaan Olij <mux213@gmail.com> | 2022-09-12 19:44:48 +1000 |
---|---|---|
committer | Bastiaan Olij <mux213@gmail.com> | 2022-10-04 11:03:32 +1100 |
commit | ddc4ae117595e2059404170ff3e8c6040413b219 (patch) | |
tree | 2c4b14075af62948dae024238a143f8a4beb14a6 /servers/rendering/renderer_rd/forward_mobile | |
parent | 4b52c6caef8a9e5d940ce0977d5c467296ac5805 (diff) |
Move cluster builder, sdfgi and gi structures to clustered renderer, move light and probe elements into storage and reorganise our render_scene method.
Diffstat (limited to 'servers/rendering/renderer_rd/forward_mobile')
-rw-r--r-- | servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp | 460 | ||||
-rw-r--r-- | servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h | 104 |
2 files changed, 429 insertions, 135 deletions
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 f458063aea..c3ce1b05f1 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -39,7 +39,7 @@ using namespace RendererSceneRenderImplementation; -RenderForwardMobile::ForwardID RenderForwardMobile::_allocate_forward_id(ForwardIDType p_type) { +RendererRD::ForwardID RenderForwardMobile::ForwardIDStorageMobile::allocate_forward_id(RendererRD::ForwardIDType p_type) { int32_t index = -1; for (uint32_t i = 0; i < forward_id_allocators[p_type].allocations.size(); i++) { if (forward_id_allocators[p_type].allocations[i] == false) { @@ -58,15 +58,66 @@ RenderForwardMobile::ForwardID RenderForwardMobile::_allocate_forward_id(Forward return index; } -void RenderForwardMobile::_free_forward_id(ForwardIDType p_type, ForwardID p_id) { - ERR_FAIL_INDEX(p_id, (ForwardID)forward_id_allocators[p_type].allocations.size()); +void RenderForwardMobile::ForwardIDStorageMobile::free_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id) { + ERR_FAIL_INDEX(p_id, (RendererRD::ForwardID)forward_id_allocators[p_type].allocations.size()); forward_id_allocators[p_type].allocations[p_id] = false; } -void RenderForwardMobile::_map_forward_id(ForwardIDType p_type, ForwardID p_id, uint32_t p_index) { +void RenderForwardMobile::ForwardIDStorageMobile::map_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id, uint32_t p_index) { forward_id_allocators[p_type].map[p_id] = p_index; } +void RenderForwardMobile::ForwardIDStorageMobile::fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, uint32_t &spec_constants, const GeometryInstanceForwardMobile *p_instance) { + // first zero out our indices + + p_push_constant->omni_lights[0] = 0xFFFF; + p_push_constant->omni_lights[1] = 0xFFFF; + + p_push_constant->spot_lights[0] = 0xFFFF; + p_push_constant->spot_lights[1] = 0xFFFF; + + p_push_constant->decals[0] = 0xFFFF; + p_push_constant->decals[1] = 0xFFFF; + + p_push_constant->reflection_probes[0] = 0xFFFF; + p_push_constant->reflection_probes[1] = 0xFFFF; + + if (p_instance->omni_light_count == 0) { + spec_constants |= 1 << SPEC_CONSTANT_DISABLE_OMNI_LIGHTS; + } + if (p_instance->spot_light_count == 0) { + spec_constants |= 1 << SPEC_CONSTANT_DISABLE_SPOT_LIGHTS; + } + if (p_instance->reflection_probe_count == 0) { + spec_constants |= 1 << SPEC_CONSTANT_DISABLE_REFLECTION_PROBES; + } + if (p_instance->decals_count == 0) { + spec_constants |= 1 << SPEC_CONSTANT_DISABLE_DECALS; + } + + for (uint32_t i = 0; i < MAX_RDL_CULL; i++) { + uint32_t ofs = i < 4 ? 0 : 1; + uint32_t shift = (i & 0x3) << 3; + uint32_t mask = ~(0xFF << shift); + if (i < p_instance->omni_light_count) { + p_push_constant->omni_lights[ofs] &= mask; + p_push_constant->omni_lights[ofs] |= uint32_t(forward_id_allocators[RendererRD::FORWARD_ID_TYPE_OMNI_LIGHT].map[p_instance->omni_lights[i]]) << shift; + } + if (i < p_instance->spot_light_count) { + p_push_constant->spot_lights[ofs] &= mask; + p_push_constant->spot_lights[ofs] |= uint32_t(forward_id_allocators[RendererRD::FORWARD_ID_TYPE_SPOT_LIGHT].map[p_instance->spot_lights[i]]) << shift; + } + if (i < p_instance->decals_count) { + p_push_constant->decals[ofs] &= mask; + p_push_constant->decals[ofs] |= uint32_t(forward_id_allocators[RendererRD::FORWARD_ID_TYPE_DECAL].map[p_instance->decals[i]]) << shift; + } + if (i < p_instance->reflection_probe_count) { + p_push_constant->reflection_probes[ofs] &= mask; + p_push_constant->reflection_probes[ofs] |= uint32_t(forward_id_allocators[RendererRD::FORWARD_ID_TYPE_REFLECTION_PROBE].map[p_instance->reflection_probes[i]]) << shift; + } + } +} + /* Render buffer */ void RenderForwardMobile::RenderBufferDataForwardMobile::free_data() { @@ -300,6 +351,7 @@ bool RenderForwardMobile::_render_buffers_can_be_storage() { } RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas, int p_index) { + RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); //there should always be enough uniform buffers for render passes, otherwise bugs @@ -340,7 +392,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ } { - RID ref_texture = (p_render_data && p_render_data->reflection_atlas.is_valid()) ? reflection_atlas_get_texture(p_render_data->reflection_atlas) : RID(); + RID ref_texture = (p_render_data && p_render_data->reflection_atlas.is_valid()) ? light_storage->reflection_atlas_get_texture(p_render_data->reflection_atlas) : RID(); RD::Uniform u; u.binding = 3; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; @@ -358,7 +410,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; RID texture; if (p_render_data && p_render_data->shadow_atlas.is_valid()) { - texture = shadow_atlas_get_texture(p_render_data->shadow_atlas); + texture = light_storage->shadow_atlas_get_texture(p_render_data->shadow_atlas); } if (!texture.is_valid()) { texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH); @@ -370,8 +422,8 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ RD::Uniform u; u.binding = 5; u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) { - u.append_id(directional_shadow_get_texture()); + if (p_use_directional_shadow_atlas && light_storage->directional_shadow_get_texture().is_valid()) { + u.append_id(light_storage->directional_shadow_get_texture()); } else { u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH)); } @@ -387,8 +439,8 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) { if (p_render_data && i < p_render_data->lightmaps->size()) { - RID base = lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]); - RID texture = RendererRD::LightStorage::get_singleton()->lightmap_get_texture(base); + RID base = light_storage->lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]); + RID texture = light_storage->lightmap_get_texture(base); RID rd_texture = texture_storage->texture_get_rd_texture(texture); u.append_id(rd_texture); } else { @@ -467,6 +519,8 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_ } void RenderForwardMobile::_setup_lightmaps(const RenderDataRD *p_render_data, const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform) { + RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); + // This probably needs to change... scene_state.lightmaps_used = 0; for (int i = 0; i < (int)p_lightmaps.size(); i++) { @@ -474,20 +528,20 @@ void RenderForwardMobile::_setup_lightmaps(const RenderDataRD *p_render_data, co break; } - RID lightmap = lightmap_instance_get_lightmap(p_lightmaps[i]); + RID lightmap = light_storage->lightmap_instance_get_lightmap(p_lightmaps[i]); - Basis to_lm = lightmap_instance_get_transform(p_lightmaps[i]).basis.inverse() * p_cam_transform.basis; + Basis to_lm = light_storage->lightmap_instance_get_transform(p_lightmaps[i]).basis.inverse() * p_cam_transform.basis; to_lm = to_lm.inverse().transposed(); //will transform normals RendererRD::MaterialStorage::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform); scene_state.lightmaps[i].exposure_normalization = 1.0; if (p_render_data->camera_attributes.is_valid()) { - float baked_exposure = RendererRD::LightStorage::get_singleton()->lightmap_get_baked_exposure_normalization(lightmap); + float baked_exposure = light_storage->lightmap_get_baked_exposure_normalization(lightmap); float enf = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes); scene_state.lightmaps[i].exposure_normalization = enf / baked_exposure; } scene_state.lightmap_ids[i] = p_lightmaps[i]; - scene_state.lightmap_has_sh[i] = RendererRD::LightStorage::get_singleton()->lightmap_uses_spherical_harmonics(lightmap); + scene_state.lightmap_has_sh[i] = light_storage->lightmap_uses_spherical_harmonics(lightmap); scene_state.lightmaps_used++; } @@ -496,12 +550,103 @@ void RenderForwardMobile::_setup_lightmaps(const RenderDataRD *p_render_data, co } } +void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) { + RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + + p_render_data->cube_shadows.clear(); + p_render_data->shadows.clear(); + p_render_data->directional_shadows.clear(); + + Plane camera_plane(-p_render_data->scene_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->scene_data->cam_transform.origin); + float lod_distance_multiplier = p_render_data->scene_data->cam_projection.get_lod_multiplier(); + { + for (int i = 0; i < p_render_data->render_shadow_count; i++) { + RID li = p_render_data->render_shadows[i].light; + RID base = light_storage->light_instance_get_base_light(li); + + if (light_storage->light_get_type(base) == RS::LIGHT_DIRECTIONAL) { + p_render_data->directional_shadows.push_back(i); + } else if (light_storage->light_get_type(base) == RS::LIGHT_OMNI && light_storage->light_omni_get_shadow_mode(base) == RS::LIGHT_OMNI_SHADOW_CUBE) { + p_render_data->cube_shadows.push_back(i); + } else { + p_render_data->shadows.push_back(i); + } + } + + //cube shadows are rendered in their own way + for (uint32_t i = 0; i < p_render_data->cube_shadows.size(); i++) { + _render_shadow_pass(p_render_data->render_shadows[p_render_data->cube_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->cube_shadows[i]].pass, p_render_data->render_shadows[p_render_data->cube_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info); + } + + if (p_render_data->directional_shadows.size()) { + //open the pass for directional shadows + light_storage->update_directional_shadow_atlas(); + RD::get_singleton()->draw_list_begin(light_storage->direction_shadow_get_fb(), RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE); + RD::get_singleton()->draw_list_end(); + } + } + + bool render_shadows = p_render_data->directional_shadows.size() || p_render_data->shadows.size(); + + if (render_shadows) { + RENDER_TIMESTAMP("Render Shadows"); + } + + //prepare shadow rendering + if (render_shadows) { + _render_shadow_begin(); + + //render directional shadows + for (uint32_t i = 0; i < p_render_data->directional_shadows.size(); i++) { + _render_shadow_pass(p_render_data->render_shadows[p_render_data->directional_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->directional_shadows[i]].pass, p_render_data->render_shadows[p_render_data->directional_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, false, i == p_render_data->directional_shadows.size() - 1, false, p_render_data->render_info); + } + //render positional shadows + for (uint32_t i = 0; i < p_render_data->shadows.size(); i++) { + _render_shadow_pass(p_render_data->render_shadows[p_render_data->shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->shadows[i]].pass, p_render_data->render_shadows[p_render_data->shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, i == 0, i == p_render_data->shadows.size() - 1, true, p_render_data->render_info); + } + + _render_shadow_process(); + + _render_shadow_end(RD::BARRIER_MASK_NO_BARRIER); + } + + //full barrier here, we need raster, transfer and compute and it depends from the previous work + RD::get_singleton()->barrier(RD::BARRIER_MASK_ALL, RD::BARRIER_MASK_ALL); + + bool using_shadows = true; + + if (p_render_data->reflection_probe.is_valid()) { + if (!RSG::light_storage->reflection_probe_renders_shadows(light_storage->reflection_probe_instance_get_probe(p_render_data->reflection_probe))) { + using_shadows = false; + } + } else { + //do not render reflections when rendering a reflection probe + light_storage->update_reflection_probe_buffer(p_render_data, *p_render_data->reflection_probes, p_render_data->scene_data->cam_transform.affine_inverse(), p_render_data->environment); + } + + uint32_t directional_light_count = 0; + uint32_t positional_light_count = 0; + light_storage->update_light_buffers(p_render_data, *p_render_data->lights, p_render_data->scene_data->cam_transform, p_render_data->shadow_atlas, using_shadows, directional_light_count, positional_light_count, p_render_data->directional_light_soft_shadows); + texture_storage->update_decal_buffer(*p_render_data->decals, p_render_data->scene_data->cam_transform.affine_inverse()); + + p_render_data->directional_light_count = directional_light_count; +} + void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) { + RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); + + Ref<RenderSceneBuffersRD> rb; Ref<RenderBufferDataForwardMobile> rb_data; if (p_render_data->render_buffers.is_valid()) { - rb_data = p_render_data->render_buffers->get_custom_data(RB_SCOPE_MOBILE); + rb = p_render_data->render_buffers; + rb_data = rb->get_custom_data(RB_SCOPE_MOBILE); } + RENDER_TIMESTAMP("Prepare 3D Scene"); + + _update_vrs(rb); + RENDER_TIMESTAMP("Setup 3D Scene"); /* TODO @@ -532,9 +677,6 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color bool using_subpass_transparent = true; bool using_subpass_post_process = true; - bool using_ssr = false; // I don't think we support this in our mobile renderer so probably should phase it out - bool using_sss = false; // I don't think we support this in our mobile renderer so probably should phase it out - // fill our render lists early so we can find out if we use various features _fill_render_list(RENDER_LIST_OPAQUE, p_render_data, PASS_MODE_COLOR); render_list[RENDER_LIST_OPAQUE].sort_by_key(); @@ -559,7 +701,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color using_subpass_post_process = false; } - if (using_ssr || using_sss || scene_state.used_screen_texture || scene_state.used_depth_texture) { + if (scene_state.used_screen_texture || scene_state.used_depth_texture) { // can't use our last two subpasses using_subpass_transparent = false; using_subpass_post_process = false; @@ -576,13 +718,13 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_TWO_SUBPASSES); } } else if (p_render_data->reflection_probe.is_valid()) { - uint32_t resolution = reflection_probe_instance_get_resolution(p_render_data->reflection_probe); + uint32_t resolution = light_storage->reflection_probe_instance_get_resolution(p_render_data->reflection_probe); screen_size.x = resolution; screen_size.y = resolution; - framebuffer = reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass); + framebuffer = light_storage->reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass); - if (RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) { + if (light_storage->reflection_probe_is_interior(light_storage->reflection_probe_instance_get_probe(p_render_data->reflection_probe))) { p_render_data->environment = RID(); //no environment on interiors } @@ -713,8 +855,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color RD::get_singleton()->draw_command_end_label(); // Setup Sky resolution buffers } - RID nullrids[RendererSceneRender::MAX_RENDER_VIEWS]; - _pre_opaque_render(p_render_data, false, false, false, nullrids, RID()); + _pre_opaque_render(p_render_data); uint32_t spec_constant_base_flags = 0; @@ -758,8 +899,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, p_render_data, radiance_texture, true); - bool can_continue_color = !using_subpass_transparent && !scene_state.used_screen_texture && !using_ssr && !using_sss; - bool can_continue_depth = !using_subpass_transparent && !scene_state.used_depth_texture && !using_ssr && !using_sss; + bool can_continue_color = !using_subpass_transparent && !scene_state.used_screen_texture; + bool can_continue_depth = !using_subpass_transparent && !scene_state.used_depth_texture; { // regular forward for now @@ -917,10 +1058,190 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color if (rb_data.is_valid()) { _disable_clear_request(p_render_data); } + + if (rb.is_valid()) { + _render_buffers_debug_draw(rb, p_render_data->shadow_atlas, p_render_data->occluder_debug_tex); + } } /* these are being called from RendererSceneRenderRD::_pre_opaque_render */ +void RenderForwardMobile::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RenderingMethod::RenderInfo *p_render_info) { + RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); + + ERR_FAIL_COND(!light_storage->owns_light_instance(p_light)); + + RID base = light_storage->light_instance_get_base_light(p_light); + + Rect2i atlas_rect; + uint32_t atlas_size = 1; + RID atlas_fb; + + bool using_dual_paraboloid = false; + bool using_dual_paraboloid_flip = false; + Vector2i dual_paraboloid_offset; + RID render_fb; + RID render_texture; + float zfar; + + bool use_pancake = false; + bool render_cubemap = false; + bool finalize_cubemap = false; + + bool flip_y = false; + + Projection light_projection; + Transform3D light_transform; + + if (light_storage->light_get_type(base) == RS::LIGHT_DIRECTIONAL) { + //set pssm stuff + uint64_t last_scene_shadow_pass = light_storage->light_instance_get_shadow_pass(p_light); + if (last_scene_shadow_pass != get_scene_pass()) { + light_storage->light_instance_set_directional_rect(p_light, light_storage->get_directional_shadow_rect()); + light_storage->directional_shadow_increase_current_light(); + light_storage->light_instance_set_shadow_pass(p_light, get_scene_pass()); + } + + use_pancake = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE) > 0; + light_projection = light_storage->light_instance_get_shadow_camera(p_light, p_pass); + light_transform = light_storage->light_instance_get_shadow_transform(p_light, p_pass); + + atlas_rect = light_storage->light_instance_get_directional_rect(p_light); + + if (light_storage->light_directional_get_shadow_mode(base) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { + atlas_rect.size.width /= 2; + atlas_rect.size.height /= 2; + + if (p_pass == 1) { + atlas_rect.position.x += atlas_rect.size.width; + } else if (p_pass == 2) { + atlas_rect.position.y += atlas_rect.size.height; + } else if (p_pass == 3) { + atlas_rect.position += atlas_rect.size; + } + } else if (light_storage->light_directional_get_shadow_mode(base) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) { + atlas_rect.size.height /= 2; + + if (p_pass == 0) { + } else { + atlas_rect.position.y += atlas_rect.size.height; + } + } + + int directional_shadow_size = light_storage->directional_shadow_get_size(); + atlas_rect.position /= directional_shadow_size; + atlas_rect.size /= directional_shadow_size; + + light_storage->light_instance_set_directional_shadow_atlas_rect(p_light, p_pass, atlas_rect); + + zfar = RSG::light_storage->light_get_param(base, RS::LIGHT_PARAM_RANGE); + + render_fb = light_storage->direction_shadow_get_fb(); + render_texture = RID(); + flip_y = true; + + } else { + //set from shadow atlas + + ERR_FAIL_COND(!light_storage->owns_shadow_atlas(p_shadow_atlas)); + ERR_FAIL_COND(!light_storage->shadow_atlas_owns_light_instance(p_shadow_atlas, p_light)); + + RSG::light_storage->shadow_atlas_update(p_shadow_atlas); + + uint32_t key = light_storage->shadow_atlas_get_light_instance_key(p_shadow_atlas, p_light); + + uint32_t quadrant = (key >> RendererRD::LightStorage::QUADRANT_SHIFT) & 0x3; + uint32_t shadow = key & RendererRD::LightStorage::SHADOW_INDEX_MASK; + uint32_t subdivision = light_storage->shadow_atlas_get_quadrant_subdivision(p_shadow_atlas, quadrant); + + ERR_FAIL_INDEX((int)shadow, light_storage->shadow_atlas_get_quadrant_shadow_size(p_shadow_atlas, quadrant)); + + uint32_t shadow_atlas_size = light_storage->shadow_atlas_get_size(p_shadow_atlas); + uint32_t quadrant_size = shadow_atlas_size >> 1; + + atlas_rect.position.x = (quadrant & 1) * quadrant_size; + atlas_rect.position.y = (quadrant >> 1) * quadrant_size; + + uint32_t shadow_size = (quadrant_size / subdivision); + atlas_rect.position.x += (shadow % subdivision) * shadow_size; + atlas_rect.position.y += (shadow / subdivision) * shadow_size; + + atlas_rect.size.width = shadow_size; + atlas_rect.size.height = shadow_size; + + zfar = light_storage->light_get_param(base, RS::LIGHT_PARAM_RANGE); + + if (light_storage->light_get_type(base) == RS::LIGHT_OMNI) { + bool wrap = (shadow + 1) % subdivision == 0; + dual_paraboloid_offset = wrap ? Vector2i(1 - subdivision, 1) : Vector2i(1, 0); + + if (light_storage->light_omni_get_shadow_mode(base) == RS::LIGHT_OMNI_SHADOW_CUBE) { + render_texture = light_storage->get_cubemap(shadow_size / 2); + render_fb = light_storage->get_cubemap_fb(shadow_size / 2, p_pass); + + light_projection = light_storage->light_instance_get_shadow_camera(p_light, p_pass); + light_transform = light_storage->light_instance_get_shadow_transform(p_light, p_pass); + render_cubemap = true; + finalize_cubemap = p_pass == 5; + atlas_fb = light_storage->shadow_atlas_get_fb(p_shadow_atlas); + + atlas_size = shadow_atlas_size; + + if (p_pass == 0) { + _render_shadow_begin(); + } + + } else { + atlas_rect.position.x += 1; + atlas_rect.position.y += 1; + atlas_rect.size.x -= 2; + atlas_rect.size.y -= 2; + + atlas_rect.position += p_pass * atlas_rect.size * dual_paraboloid_offset; + + light_projection = light_storage->light_instance_get_shadow_camera(p_light, 0); + light_transform = light_storage->light_instance_get_shadow_transform(p_light, 0); + + using_dual_paraboloid = true; + using_dual_paraboloid_flip = p_pass == 1; + render_fb = light_storage->shadow_atlas_get_fb(p_shadow_atlas); + flip_y = true; + } + + } else if (light_storage->light_get_type(base) == RS::LIGHT_SPOT) { + light_projection = light_storage->light_instance_get_shadow_camera(p_light, 0); + light_transform = light_storage->light_instance_get_shadow_transform(p_light, 0); + + render_fb = light_storage->shadow_atlas_get_fb(p_shadow_atlas); + + flip_y = true; + } + } + + if (render_cubemap) { + //rendering to cubemap + _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, Rect2(), false, true, true, true, p_render_info); + if (finalize_cubemap) { + _render_shadow_process(); + _render_shadow_end(); + //reblit + Rect2 atlas_rect_norm = atlas_rect; + atlas_rect_norm.position /= float(atlas_size); + atlas_rect_norm.size /= float(atlas_size); + 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; + 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_storage->light_instance_set_shadow_transform(p_light, Projection(), light_storage->light_instance_get_base_transform(p_light), zfar, 0, 0, 0); + } + + } else { + //render shadow + _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, atlas_rect, flip_y, p_clear_region, p_open_pass, p_close_pass, p_render_info); + } +} + void RenderForwardMobile::_render_shadow_begin() { scene_state.shadow_passes.clear(); RD::get_singleton()->draw_command_begin_label("Shadow Setup"); @@ -1146,7 +1467,7 @@ void RenderForwardMobile::_render_uv2(const PagedArray<RenderGeometryInstance *> } void RenderForwardMobile::_render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) { - // we don't do GI in low end.. + // we don't do SDFGI in low end.. } void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) { @@ -1189,7 +1510,7 @@ void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const RD::get_singleton()->draw_command_end_label(); } -void RenderForwardMobile::_base_uniforms_changed() { +void RenderForwardMobile::base_uniforms_changed() { if (!render_base_uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { RD::get_singleton()->free(render_base_uniform_set); } @@ -1305,14 +1626,14 @@ void RenderForwardMobile::_update_render_base_uniform_set() { RD::Uniform u; u.binding = 5; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.append_id(get_omni_light_buffer()); + u.append_id(RendererRD::LightStorage::get_singleton()->get_omni_light_buffer()); uniforms.push_back(u); } { RD::Uniform u; u.binding = 6; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.append_id(get_spot_light_buffer()); + u.append_id(RendererRD::LightStorage::get_singleton()->get_spot_light_buffer()); uniforms.push_back(u); } @@ -1320,14 +1641,14 @@ void RenderForwardMobile::_update_render_base_uniform_set() { RD::Uniform u; u.binding = 7; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.append_id(get_reflection_probe_buffer()); + u.append_id(RendererRD::LightStorage::get_singleton()->get_reflection_probe_buffer()); uniforms.push_back(u); } { RD::Uniform u; u.binding = 8; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.append_id(get_directional_light_buffer()); + u.append_id(RendererRD::LightStorage::get_singleton()->get_directional_light_buffer()); uniforms.push_back(u); } { @@ -1364,7 +1685,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() { RD::Uniform u; u.binding = 13; u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.append_id(get_decal_buffer()); + u.append_id(RendererRD::TextureStorage::get_singleton()->get_decal_buffer()); uniforms.push_back(u); } @@ -1584,7 +1905,7 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers, bool p_pancake_shadows, int p_index) { Ref<RenderSceneBuffersRD> rd = p_render_data->render_buffers; RID env = is_environment(p_render_data->environment) ? p_render_data->environment : RID(); - RID reflection_probe_instance = p_render_data->reflection_probe.is_valid() ? reflection_probe_instance_get_probe(p_render_data->reflection_probe) : RID(); + RID reflection_probe_instance = p_render_data->reflection_probe.is_valid() ? RendererRD::LightStorage::get_singleton()->reflection_probe_instance_get_probe(p_render_data->reflection_probe) : RID(); // May do this earlier in RenderSceneRenderRD::render_scene if (p_index >= (int)scene_state.uniform_buffers.size()) { @@ -1665,57 +1986,6 @@ void RenderForwardMobile::_render_list_with_threads(RenderListParameters *p_para } } -void RenderForwardMobile::_fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, uint32_t &spec_constants, const GeometryInstanceForwardMobile *p_instance) { - // first zero out our indices - - p_push_constant->omni_lights[0] = 0xFFFF; - p_push_constant->omni_lights[1] = 0xFFFF; - - p_push_constant->spot_lights[0] = 0xFFFF; - p_push_constant->spot_lights[1] = 0xFFFF; - - p_push_constant->decals[0] = 0xFFFF; - p_push_constant->decals[1] = 0xFFFF; - - p_push_constant->reflection_probes[0] = 0xFFFF; - p_push_constant->reflection_probes[1] = 0xFFFF; - - if (p_instance->omni_light_count == 0) { - spec_constants |= 1 << SPEC_CONSTANT_DISABLE_OMNI_LIGHTS; - } - if (p_instance->spot_light_count == 0) { - spec_constants |= 1 << SPEC_CONSTANT_DISABLE_SPOT_LIGHTS; - } - if (p_instance->reflection_probe_count == 0) { - spec_constants |= 1 << SPEC_CONSTANT_DISABLE_REFLECTION_PROBES; - } - if (p_instance->decals_count == 0) { - spec_constants |= 1 << SPEC_CONSTANT_DISABLE_DECALS; - } - - for (uint32_t i = 0; i < MAX_RDL_CULL; i++) { - uint32_t ofs = i < 4 ? 0 : 1; - uint32_t shift = (i & 0x3) << 3; - uint32_t mask = ~(0xFF << shift); - if (i < p_instance->omni_light_count) { - p_push_constant->omni_lights[ofs] &= mask; - p_push_constant->omni_lights[ofs] |= uint32_t(forward_id_allocators[FORWARD_ID_TYPE_OMNI_LIGHT].map[p_instance->omni_lights[i]]) << shift; - } - if (i < p_instance->spot_light_count) { - p_push_constant->spot_lights[ofs] &= mask; - p_push_constant->spot_lights[ofs] |= uint32_t(forward_id_allocators[FORWARD_ID_TYPE_SPOT_LIGHT].map[p_instance->spot_lights[i]]) << shift; - } - if (i < p_instance->decals_count) { - p_push_constant->decals[ofs] &= mask; - p_push_constant->decals[ofs] |= uint32_t(forward_id_allocators[FORWARD_ID_TYPE_DECAL].map[p_instance->decals[i]]) << shift; - } - if (i < p_instance->reflection_probe_count) { - p_push_constant->reflection_probes[ofs] &= mask; - p_push_constant->reflection_probes[ofs] |= uint32_t(forward_id_allocators[FORWARD_ID_TYPE_REFLECTION_PROBE].map[p_instance->reflection_probes[i]]) << shift; - } - } -} - template <RenderForwardMobile::PassMode p_pass_mode> void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) { RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); @@ -1797,7 +2067,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr if (inst->use_soft_shadow) { base_spec_constants |= 1 << SPEC_CONSTANT_USING_SOFT_SHADOWS; } - _fill_push_constant_instance_indices(&push_constant, base_spec_constants, inst); + forward_id_storage_mobile->fill_push_constant_instance_indices(&push_constant, base_spec_constants, inst); #ifdef DEBUG_ENABLED if (unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_LIGHTING)) { @@ -1989,17 +2259,17 @@ void RenderForwardMobile::GeometryInstanceForwardMobile::pair_light_instances(co spot_light_count = 0; for (uint32_t i = 0; i < p_light_instance_count; i++) { - RS::LightType type = RenderForwardMobile::get_singleton()->light_instance_get_type(p_light_instances[i]); + RS::LightType type = RendererRD::LightStorage::get_singleton()->light_instance_get_type(p_light_instances[i]); switch (type) { case RS::LIGHT_OMNI: { if (omni_light_count < (uint32_t)MAX_RDL_CULL) { - omni_lights[omni_light_count] = RenderForwardMobile::get_singleton()->light_instance_get_forward_id(p_light_instances[i]); + omni_lights[omni_light_count] = RendererRD::LightStorage::get_singleton()->light_instance_get_forward_id(p_light_instances[i]); omni_light_count++; } } break; case RS::LIGHT_SPOT: { if (spot_light_count < (uint32_t)MAX_RDL_CULL) { - spot_lights[spot_light_count] = RenderForwardMobile::get_singleton()->light_instance_get_forward_id(p_light_instances[i]); + spot_lights[spot_light_count] = RendererRD::LightStorage::get_singleton()->light_instance_get_forward_id(p_light_instances[i]); spot_light_count++; } } break; @@ -2012,14 +2282,14 @@ void RenderForwardMobile::GeometryInstanceForwardMobile::pair_light_instances(co void RenderForwardMobile::GeometryInstanceForwardMobile::pair_reflection_probe_instances(const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) { reflection_probe_count = p_reflection_probe_instance_count < (uint32_t)MAX_RDL_CULL ? p_reflection_probe_instance_count : (uint32_t)MAX_RDL_CULL; for (uint32_t i = 0; i < reflection_probe_count; i++) { - reflection_probes[i] = RenderForwardMobile::get_singleton()->reflection_probe_instance_get_forward_id(p_reflection_probe_instances[i]); + reflection_probes[i] = RendererRD::LightStorage::get_singleton()->reflection_probe_instance_get_forward_id(p_reflection_probe_instances[i]); } } void RenderForwardMobile::GeometryInstanceForwardMobile::pair_decal_instances(const RID *p_decal_instances, uint32_t p_decal_instance_count) { decals_count = p_decal_instance_count < (uint32_t)MAX_RDL_CULL ? p_decal_instance_count : (uint32_t)MAX_RDL_CULL; for (uint32_t i = 0; i < decals_count; i++) { - decals[i] = RenderForwardMobile::get_singleton()->decal_instance_get_forward_id(p_decal_instances[i]); + decals[i] = RendererRD::TextureStorage::get_singleton()->decal_instance_get_forward_id(p_decal_instances[i]); } } @@ -2387,10 +2657,6 @@ bool RenderForwardMobile::is_dynamic_gi_supported() const { return false; } -bool RenderForwardMobile::is_clustered_enabled() const { - return false; -} - bool RenderForwardMobile::is_volumetric_supported() const { return false; } @@ -2446,7 +2712,7 @@ void RenderForwardMobile::_update_shader_quality_settings() { scene_shader.set_default_specialization_constants(spec_constants); - _base_uniforms_changed(); //also need this + base_uniforms_changed(); //also need this } RenderForwardMobile::RenderForwardMobile() { @@ -2495,7 +2761,7 @@ RenderForwardMobile::RenderForwardMobile() { } RenderForwardMobile::~RenderForwardMobile() { - directional_shadow_atlas_set_size(0); + RSG::light_storage->directional_shadow_atlas_set_size(0); //clear base uniform set if still valid for (uint32_t i = 0; i < render_pass_uniform_sets.size(); i++) { 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 a53872fc88..16ac5514f6 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -44,19 +44,12 @@ namespace RendererSceneRenderImplementation { class RenderForwardMobile : public RendererSceneRenderRD { friend SceneShaderForwardMobile; - struct ForwardIDAllocator { - LocalVector<bool> allocations; - LocalVector<uint8_t> map; - }; - - ForwardIDAllocator forward_id_allocators[FORWARD_ID_MAX]; +protected: + struct GeometryInstanceSurfaceDataCache; - virtual ForwardID _allocate_forward_id(ForwardIDType p_type) override; - virtual void _free_forward_id(ForwardIDType p_type, ForwardID p_id) override; - virtual void _map_forward_id(ForwardIDType p_type, ForwardID p_id, uint32_t p_index) override; - virtual bool _uses_forward_ids() const override { return true; } +private: + static RenderForwardMobile *singleton; -protected: /* Scene Shader */ enum { @@ -157,8 +150,6 @@ protected: // PASS_MODE_SDF, }; - class GeometryInstanceForwardMobile; - struct GeometryInstanceSurfaceDataCache; struct RenderElementInfo; struct RenderListParameters { @@ -201,36 +192,27 @@ protected: } }; - virtual float _render_buffers_get_luminance_multiplier() override; - virtual RD::DataFormat _render_buffers_get_color_format() override; - virtual bool _render_buffers_can_be_storage() override; + /* Render shadows */ - RID _setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas = false, int p_index = 0); - virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override; + void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RenderingMethod::RenderInfo *p_render_info = nullptr); + void _render_shadow_begin(); + void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RenderingMethod::RenderInfo *p_render_info = nullptr); + void _render_shadow_process(); + void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL); - virtual void _render_shadow_begin() override; - virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RenderingMethod::RenderInfo *p_render_info = nullptr) override; - virtual void _render_shadow_process() override; - virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) override; + /* Render Scene */ - virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) override; - virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; - virtual void _render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override; - virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) override; + RID _setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas = false, int p_index = 0); + void _pre_opaque_render(RenderDataRD *p_render_data); uint64_t lightmap_texture_array_version = 0xFFFFFFFF; - virtual void _base_uniforms_changed() override; void _update_render_base_uniform_set(); - virtual RID _render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override; - virtual RID _render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> 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); // void _update_instance_data_buffer(RenderListType p_render_list); - static RenderForwardMobile *singleton; - void _setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false, int p_index = 0); void _setup_lightmaps(const RenderDataRD *p_render_data, const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform); @@ -369,8 +351,21 @@ protected: RenderList render_list[RENDER_LIST_MAX]; +protected: + /* setup */ + virtual void _update_shader_quality_settings() override; + + virtual float _render_buffers_get_luminance_multiplier() override; + virtual RD::DataFormat _render_buffers_get_color_format() override; + virtual bool _render_buffers_can_be_storage() override; + + virtual RID _render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override; + virtual RID _render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override; + /* Geometry instance */ + class GeometryInstanceForwardMobile; + // When changing any of these enums, remember to change the corresponding enums in the shader files as well. enum { INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 4, @@ -484,13 +479,13 @@ protected: // culled light info uint32_t reflection_probe_count = 0; - ForwardID reflection_probes[MAX_RDL_CULL]; + RendererRD::ForwardID reflection_probes[MAX_RDL_CULL]; uint32_t omni_light_count = 0; - ForwardID omni_lights[MAX_RDL_CULL]; + RendererRD::ForwardID omni_lights[MAX_RDL_CULL]; uint32_t spot_light_count = 0; - ForwardID spot_lights[MAX_RDL_CULL]; + RendererRD::ForwardID spot_lights[MAX_RDL_CULL]; uint32_t decals_count = 0; - ForwardID decals[MAX_RDL_CULL]; + RendererRD::ForwardID decals[MAX_RDL_CULL]; GeometryInstanceSurfaceDataCache *surface_caches = nullptr; @@ -513,9 +508,41 @@ protected: virtual void set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) override; }; - _FORCE_INLINE_ void _fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, uint32_t &spec_constants, const GeometryInstanceForwardMobile *p_instance); + /* Rendering */ + + virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override; + + virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) override; + virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override; + virtual void _render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override; + virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) override; + + /* Forward ID */ + + class ForwardIDStorageMobile : public RendererRD::ForwardIDStorage { + public: + struct ForwardIDAllocator { + LocalVector<bool> allocations; + LocalVector<uint8_t> map; + }; + + ForwardIDAllocator forward_id_allocators[RendererRD::FORWARD_ID_MAX]; + + public: + virtual RendererRD::ForwardID allocate_forward_id(RendererRD::ForwardIDType p_type) override; + virtual void free_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id) override; + virtual void map_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id, uint32_t p_index) override; + virtual bool uses_forward_ids() const override { return true; } + + void fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, uint32_t &spec_constants, const GeometryInstanceForwardMobile *p_instance); + }; + + ForwardIDStorageMobile *forward_id_storage_mobile = nullptr; - void _update_shader_quality_settings() override; + virtual RendererRD::ForwardIDStorage *create_forward_id_storage() override { + forward_id_storage_mobile = memnew(ForwardIDStorageMobile); + return forward_id_storage_mobile; + } public: static RenderForwardMobile *get_singleton() { return singleton; } @@ -544,8 +571,9 @@ public: virtual bool free(RID p_rid) override; + virtual void base_uniforms_changed() override; + virtual bool is_dynamic_gi_supported() const override; - virtual bool is_clustered_enabled() const override; virtual bool is_volumetric_supported() const override; virtual uint32_t get_max_elements() const override; |