diff options
Diffstat (limited to 'servers/rendering/renderer_rd')
20 files changed, 1712 insertions, 950 deletions
diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp index a73eb3782c..6e1d61ff94 100644 --- a/servers/rendering/renderer_rd/effects_rd.cpp +++ b/servers/rendering/renderer_rd/effects_rd.cpp @@ -992,21 +992,21 @@ void EffectsRD::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID>  		ssao.gather_push_constant.pass_coord_offset[0] = i % 2;  		ssao.gather_push_constant.pass_coord_offset[1] = i / 2; -		ssao.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.screen_size.x; -		ssao.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.screen_size.y; +		ssao.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x; +		ssao.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y;  		ssao.gather_push_constant.pass = i;  		RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, _get_uniform_set_from_image(p_ao_slices[i]), 2);  		RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssao.gather_push_constant, sizeof(SSAOGatherPushConstant)); -		int x_groups = ((p_settings.screen_size.x >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1; -		int y_groups = ((p_settings.screen_size.y >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1; +		int x_groups = ((p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1; +		int y_groups = ((p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1;  		RD::get_singleton()->compute_list_dispatch(p_compute_list, x_groups, y_groups, 1);  	}  	RD::get_singleton()->compute_list_add_barrier(p_compute_list);  } -void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_depth_mipmaps_texture, const Vector<RID> &depth_mipmaps, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets) { +void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_depth_mipmaps_texture, const Vector<RID> &p_depth_mipmaps, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets) {  	RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();  	/* FIRST PASS */ @@ -1018,21 +1018,21 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep  				RD::Uniform u;  				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;  				u.binding = 0; -				u.ids.push_back(depth_mipmaps[1]); +				u.ids.push_back(p_depth_mipmaps[1]);  				uniforms.push_back(u);  			}  			{  				RD::Uniform u;  				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;  				u.binding = 1; -				u.ids.push_back(depth_mipmaps[2]); +				u.ids.push_back(p_depth_mipmaps[2]);  				uniforms.push_back(u);  			}  			{  				RD::Uniform u;  				u.uniform_type = RD::UNIFORM_TYPE_IMAGE;  				u.binding = 2; -				u.ids.push_back(depth_mipmaps[3]); +				u.ids.push_back(p_depth_mipmaps[3]);  				uniforms.push_back(u);  			}  			ssao.downsample_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.downsample_shader.version_get_shader(ssao.downsample_shader_version, 2), 2); @@ -1051,8 +1051,8 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep  			ssao.downsample_push_constant.z_near = p_projection.get_z_near();  			ssao.downsample_push_constant.z_far = p_projection.get_z_far();  		} -		ssao.downsample_push_constant.pixel_size[0] = 1.0 / p_settings.screen_size.x; -		ssao.downsample_push_constant.pixel_size[1] = 1.0 / p_settings.screen_size.y; +		ssao.downsample_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x; +		ssao.downsample_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;  		ssao.downsample_push_constant.radius_sq = p_settings.radius * p_settings.radius;  		int downsample_pipeline = SSAO_DOWNSAMPLE; @@ -1068,14 +1068,14 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep  		RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[downsample_pipeline]);  		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 0); -		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(depth_mipmaps[0]), 1); +		RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_depth_mipmaps[0]), 1);  		if (p_settings.quality > RS::ENV_SSAO_QUALITY_MEDIUM) {  			RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssao.downsample_uniform_set, 2);  		}  		RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.downsample_push_constant, sizeof(SSAODownsamplePushConstant)); -		int x_groups = (MAX(1, p_settings.screen_size.x >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1; -		int y_groups = (MAX(1, p_settings.screen_size.y >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1; +		int x_groups = (MAX(1, p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1; +		int y_groups = (MAX(1, p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1;  		RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);  		RD::get_singleton()->compute_list_add_barrier(compute_list); @@ -1084,8 +1084,8 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep  	/* SECOND PASS */  	// Sample SSAO  	{ -		ssao.gather_push_constant.screen_size[0] = p_settings.screen_size.x; -		ssao.gather_push_constant.screen_size[1] = p_settings.screen_size.y; +		ssao.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x; +		ssao.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;  		ssao.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x;  		ssao.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y; @@ -1122,7 +1122,7 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep  		ssao.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit;  		ssao.gather_push_constant.neg_inv_radius = -1.0 / ssao.gather_push_constant.radius; -		ssao.gather_push_constant.load_counter_avg_div = 9.0 / float((p_settings.quarter_size.x) * (p_settings.quarter_size.y) * 255); +		ssao.gather_push_constant.load_counter_avg_div = 9.0 / float((p_settings.quarter_screen_size.x) * (p_settings.quarter_screen_size.y) * 255);  		ssao.gather_push_constant.adaptive_sample_limit = p_settings.adaptive_target;  		ssao.gather_push_constant.detail_intensity = p_settings.detail; @@ -1192,8 +1192,8 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep  			RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_BASE]);  			gather_ssao(compute_list, p_ao_pong_slices, p_settings, true);  			//generate importance map -			int x_groups = (p_settings.quarter_size.x - 1) / 8 + 1; -			int y_groups = (p_settings.quarter_size.y - 1) / 8 + 1; +			int x_groups = (p_settings.quarter_screen_size.x - 1) / 8 + 1; +			int y_groups = (p_settings.quarter_screen_size.y - 1) / 8 + 1;  			RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GENERATE_IMPORTANCE_MAP]);  			RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_pong), 0); @@ -1268,8 +1268,8 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep  				}  				RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant)); -				int x_groups = ((p_settings.screen_size.x >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1; -				int y_groups = ((p_settings.screen_size.y >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1; +				int x_groups = ((p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1; +				int y_groups = ((p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1)) - 1) / 8 + 1;  				RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);  			} @@ -1285,8 +1285,8 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep  	// back to full size  	{  		ssao.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness; -		ssao.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.screen_size.x; -		ssao.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.screen_size.y; +		ssao.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x; +		ssao.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;  		ssao.interleave_push_constant.size_modifier = uint32_t(p_settings.half_size ? 4 : 2);  		int interleave_pipeline = SSAO_INTERLEAVE_HALF; @@ -1307,8 +1307,8 @@ void EffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, RID p_dep  		RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.interleave_push_constant, sizeof(SSAOInterleavePushConstant)); -		int x_groups = (p_settings.screen_size.x - 1) / 8 + 1; -		int y_groups = (p_settings.screen_size.y - 1) / 8 + 1; +		int x_groups = (p_settings.full_screen_size.x - 1) / 8 + 1; +		int y_groups = (p_settings.full_screen_size.y - 1) / 8 + 1;  		RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1);  		RD::get_singleton()->compute_list_add_barrier(compute_list); diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h index ad4a660944..e2cdd0c3d8 100644 --- a/servers/rendering/renderer_rd/effects_rd.h +++ b/servers/rendering/renderer_rd/effects_rd.h @@ -745,9 +745,9 @@ public:  		float fadeout_from = 50.0;  		float fadeout_to = 300.0; -		Size2i screen_size = Size2i(); +		Size2i full_screen_size = Size2i();  		Size2i half_screen_size = Size2i(); -		Size2i quarter_size = Size2i(); +		Size2i quarter_screen_size = Size2i();  	};  	void tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings); diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 05ffc0086d..5b3c3c703f 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -2239,6 +2239,11 @@ Variant RendererCanvasRenderRD::ShaderData::get_default_parameter(const StringNa  	return Variant();  } +RS::ShaderNativeSourceCode RendererCanvasRenderRD::ShaderData::get_native_source_code() const { +	RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton; +	return canvas_singleton->shader.canvas_shader.version_get_native_source_code(version); +} +  RendererCanvasRenderRD::ShaderData::ShaderData() {  	valid = false;  	uses_screen_texture = false; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index 545eeaa106..cb947d7180 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -188,6 +188,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender {  		virtual bool is_animated() const;  		virtual bool casts_shadows() const;  		virtual Variant get_default_parameter(const StringName &p_parameter) const; +		virtual RS::ShaderNativeSourceCode get_native_source_code() const; +  		ShaderData();  		virtual ~ShaderData();  	}; diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp index fb9c114ade..be2552bd32 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp @@ -154,12 +154,9 @@ void RendererCompositorRD::initialize() {  	}  } -ThreadWorkPool RendererCompositorRD::thread_work_pool;  uint64_t RendererCompositorRD::frame = 1;  void RendererCompositorRD::finalize() { -	thread_work_pool.finish(); -  	memdelete(scene);  	memdelete(canvas);  	memdelete(storage); @@ -174,7 +171,6 @@ RendererCompositorRD *RendererCompositorRD::singleton = nullptr;  RendererCompositorRD::RendererCompositorRD() {  	singleton = this; -	thread_work_pool.init();  	time = 0;  	storage = memnew(RendererStorageRD); diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h index e1995872af..cb85fc79e0 100644 --- a/servers/rendering/renderer_rd/renderer_compositor_rd.h +++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h @@ -90,8 +90,6 @@ public:  	virtual bool is_low_end() const { return false; } -	static ThreadWorkPool thread_work_pool; -  	static RendererCompositorRD *singleton;  	RendererCompositorRD();  	~RendererCompositorRD() {} diff --git a/servers/rendering/renderer_rd/renderer_scene_render_forward.cpp b/servers/rendering/renderer_rd/renderer_scene_render_forward.cpp index 6881d7913f..1d07741296 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_forward.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_forward.cpp @@ -394,6 +394,12 @@ Variant RendererSceneRenderForward::ShaderData::get_default_parameter(const Stri  	return Variant();  } +RS::ShaderNativeSourceCode RendererSceneRenderForward::ShaderData::get_native_source_code() const { +	RendererSceneRenderForward *scene_singleton = (RendererSceneRenderForward *)RendererSceneRenderForward::singleton; + +	return scene_singleton->shader.scene_shader.version_get_native_source_code(version); +} +  RendererSceneRenderForward::ShaderData::ShaderData() {  	valid = false;  	uses_screen_texture = false; @@ -806,252 +812,89 @@ bool RendererSceneRenderForward::free(RID p_rid) {  	return false;  } -void RendererSceneRenderForward::_fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth, bool p_has_sdfgi, bool p_has_opaque_gi) { -	uint32_t lightmap_captures_used = 0; - -	for (int i = 0; i < p_element_count; i++) { -		const RenderList::Element *e = p_elements[i]; -		InstanceData &id = scene_state.instances[i]; -		bool store_transform = true; -		id.flags = 0; -		id.mask = e->instance->layer_mask; -		id.instance_uniforms_ofs = e->instance->instance_allocated_shader_parameters_offset >= 0 ? e->instance->instance_allocated_shader_parameters_offset : 0; - -		if (e->instance->base_type == RS::INSTANCE_MULTIMESH) { -			id.flags |= INSTANCE_DATA_FLAG_MULTIMESH; -			uint32_t stride; -			if (storage->multimesh_get_transform_format(e->instance->base) == RS::MULTIMESH_TRANSFORM_2D) { -				id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D; -				stride = 2; -			} else { -				stride = 3; -			} -			if (storage->multimesh_uses_colors(e->instance->base)) { -				id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR; -				stride += 1; -			} -			if (storage->multimesh_uses_custom_data(e->instance->base)) { -				id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA; -				stride += 1; -			} - -			id.flags |= (stride << INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT); -		} else if (e->instance->base_type == RS::INSTANCE_PARTICLES) { -			id.flags |= INSTANCE_DATA_FLAG_MULTIMESH; -			uint32_t stride; -			if (false) { // 2D particles -				id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D; -				stride = 2; -			} else { -				stride = 3; -			} - -			id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR; -			stride += 1; - -			id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA; -			stride += 1; - -			id.flags |= (stride << INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT); - -			if (!storage->particles_is_using_local_coords(e->instance->base)) { -				store_transform = false; -			} - -		} else if (e->instance->base_type == RS::INSTANCE_MESH) { -			if (e->instance->skeleton.is_valid()) { -				id.flags |= INSTANCE_DATA_FLAG_SKELETON; -			} -		} - -		if (store_transform) { -			RendererStorageRD::store_transform(e->instance->transform, id.transform); -			RendererStorageRD::store_transform(Transform(e->instance->transform.basis.inverse().transposed()), id.normal_transform); -		} else { -			RendererStorageRD::store_transform(Transform(), id.transform); -			RendererStorageRD::store_transform(Transform(), id.normal_transform); -		} - -		if (p_for_depth) { -			id.gi_offset = 0xFFFFFFFF; -			continue; -		} - -		if (e->instance->lightmap) { -			int32_t lightmap_index = storage->lightmap_get_array_index(e->instance->lightmap->base); -			if (lightmap_index >= 0) { -				id.gi_offset = lightmap_index; -				id.gi_offset |= e->instance->lightmap_slice_index << 12; -				id.gi_offset |= e->instance->lightmap_cull_index << 20; -				id.lightmap_uv_scale[0] = e->instance->lightmap_uv_scale.position.x; -				id.lightmap_uv_scale[1] = e->instance->lightmap_uv_scale.position.y; -				id.lightmap_uv_scale[2] = e->instance->lightmap_uv_scale.size.width; -				id.lightmap_uv_scale[3] = e->instance->lightmap_uv_scale.size.height; -				id.flags |= INSTANCE_DATA_FLAG_USE_LIGHTMAP; -				if (storage->lightmap_uses_spherical_harmonics(e->instance->lightmap->base)) { -					id.flags |= INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP; -				} -			} else { -				id.gi_offset = 0xFFFFFFFF; -			} -		} else if (!e->instance->lightmap_sh.is_empty()) { -			if (lightmap_captures_used < scene_state.max_lightmap_captures) { -				const Color *src_capture = e->instance->lightmap_sh.ptr(); -				LightmapCaptureData &lcd = scene_state.lightmap_captures[lightmap_captures_used]; -				for (int j = 0; j < 9; j++) { -					lcd.sh[j * 4 + 0] = src_capture[j].r; -					lcd.sh[j * 4 + 1] = src_capture[j].g; -					lcd.sh[j * 4 + 2] = src_capture[j].b; -					lcd.sh[j * 4 + 3] = src_capture[j].a; -				} -				id.flags |= INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE; -				id.gi_offset = lightmap_captures_used; -				lightmap_captures_used++; -			} - -		} else { -			if (p_has_opaque_gi) { -				id.flags |= INSTANCE_DATA_FLAG_USE_GI_BUFFERS; -			} - -			if (!low_end && !e->instance->gi_probe_instances.is_empty()) { -				uint32_t written = 0; -				for (int j = 0; j < e->instance->gi_probe_instances.size(); j++) { -					RID probe = e->instance->gi_probe_instances[j]; - -					uint32_t index = gi_probe_instance_get_render_index(probe); - -					if (written == 0) { -						id.gi_offset = index; -						id.flags |= INSTANCE_DATA_FLAG_USE_GIPROBE; -						written = 1; -					} else { -						id.gi_offset = index << 16; -						written = 2; -						break; -					} -				} -				if (written == 0) { -					id.gi_offset = 0xFFFFFFFF; -				} else if (written == 1) { -					id.gi_offset |= 0xFFFF0000; -				} -			} else { -				if (p_has_sdfgi && (e->instance->baked_light || e->instance->dynamic_gi)) { -					id.flags |= INSTANCE_DATA_FLAG_USE_SDFGI; -				} -				id.gi_offset = 0xFFFFFFFF; -			} -		} -	} - -	RD::get_singleton()->buffer_update(scene_state.instance_buffer, 0, sizeof(InstanceData) * p_element_count, scene_state.instances, true); -	if (lightmap_captures_used) { -		RD::get_singleton()->buffer_update(scene_state.lightmap_capture_buffer, 0, sizeof(LightmapCaptureData) * lightmap_captures_used, scene_state.lightmap_captures, true); -	} -} -  /// RENDERING /// -void RendererSceneRenderForward::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_render_pass_uniform_set, bool p_force_wireframe, const Vector2 &p_uv_offset, const Plane &p_lod_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) { +template <RendererSceneRenderForward::PassMode p_pass_mode> +void RendererSceneRenderForward::_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) {  	RD::DrawListID draw_list = p_draw_list;  	RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format;  	//global scope bindings  	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_base_uniform_set, SCENE_UNIFORM_SET); -	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_render_pass_uniform_set, RENDER_PASS_UNIFORM_SET); +	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_params->render_pass_uniform_set, RENDER_PASS_UNIFORM_SET);  	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, default_vec4_xform_uniform_set, TRANSFORMS_UNIFORM_SET); -	MaterialData *prev_material = nullptr; +	RID prev_material_uniform_set;  	RID prev_vertex_array_rd;  	RID prev_index_array_rd;  	RID prev_pipeline_rd;  	RID prev_xforms_uniform_set; -	PushConstant push_constant; -	zeromem(&push_constant, sizeof(PushConstant)); -	push_constant.bake_uv2_offset[0] = p_uv_offset.x; -	push_constant.bake_uv2_offset[1] = p_uv_offset.y; +	bool shadow_pass = (p_params->pass_mode == PASS_MODE_SHADOW) || (p_params->pass_mode == PASS_MODE_SHADOW_DP); + +	float old_offset[2] = { 0, 0 }; + +	for (uint32_t i = p_from_element; i < p_to_element; i++) { +		const GeometryInstanceSurfaceDataCache *surf = p_params->elements[i]; -	for (int i = 0; i < p_element_count; i++) { -		const RenderList::Element *e = p_elements[i]; +		RID material_uniform_set; +		ShaderData *shader; +		void *mesh_surface; -		MaterialData *material = e->material; -		ShaderData *shader = material->shader_data; -		RID xforms_uniform_set; +		if (shadow_pass) { +			material_uniform_set = surf->material_uniform_set_shadow; +			shader = surf->shader_shadow; +			mesh_surface = surf->surface_shadow; + +		} else { +			material_uniform_set = surf->material_uniform_set; +			shader = surf->shader; +			mesh_surface = surf->surface; +		} + +		if (!mesh_surface) { +			continue; +		} + +		if (p_params->pass_mode == PASS_MODE_DEPTH_MATERIAL) { +			old_offset[0] = surf->owner->push_constant.lightmap_uv_scale[0]; +			old_offset[1] = surf->owner->push_constant.lightmap_uv_scale[1]; +			surf->owner->push_constant.lightmap_uv_scale[0] = p_params->uv_offset.x; +			surf->owner->push_constant.lightmap_uv_scale[1] = p_params->uv_offset.y; +		}  		//find cull variant  		ShaderData::CullVariant cull_variant; -		if (p_pass_mode == PASS_MODE_DEPTH_MATERIAL || p_pass_mode == PASS_MODE_SDF || ((p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) && e->instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED)) { +		if (p_params->pass_mode == PASS_MODE_DEPTH_MATERIAL || p_params->pass_mode == PASS_MODE_SDF || ((p_params->pass_mode == PASS_MODE_SHADOW || p_params->pass_mode == PASS_MODE_SHADOW_DP) && surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_DOUBLE_SIDED_SHADOWS)) {  			cull_variant = ShaderData::CULL_VARIANT_DOUBLE_SIDED;  		} else { -			bool mirror = e->instance->mirror; -			if (p_reverse_cull) { +			bool mirror = surf->owner->mirror; +			if (p_params->reverse_cull) {  				mirror = !mirror;  			}  			cull_variant = mirror ? ShaderData::CULL_VARIANT_REVERSED : ShaderData::CULL_VARIANT_NORMAL;  		} -		//find primitive and vertex format -		RS::PrimitiveType primitive; -		void *mesh_surface = nullptr; - -		switch (e->instance->base_type) { -			case RS::INSTANCE_MESH: { -				mesh_surface = storage->mesh_get_surface(e->instance->base, e->surface_index); - -				primitive = storage->mesh_surface_get_primitive(mesh_surface); -				if (e->instance->skeleton.is_valid()) { -					xforms_uniform_set = storage->skeleton_get_3d_uniform_set(e->instance->skeleton, default_shader_rd, TRANSFORMS_UNIFORM_SET); -				} -			} break; -			case RS::INSTANCE_MULTIMESH: { -				RID mesh = storage->multimesh_get_mesh(e->instance->base); -				ERR_CONTINUE(!mesh.is_valid()); //should be a bug - -				mesh_surface = storage->mesh_get_surface(e->instance->base, e->surface_index); - -				primitive = storage->mesh_surface_get_primitive(mesh_surface); - -				xforms_uniform_set = storage->multimesh_get_3d_uniform_set(e->instance->base, default_shader_rd, TRANSFORMS_UNIFORM_SET); - -			} break; -			case RS::INSTANCE_IMMEDIATE: { -				ERR_CONTINUE(true); //should be a bug -			} break; -			case RS::INSTANCE_PARTICLES: { -				RID mesh = storage->particles_get_draw_pass_mesh(e->instance->base, e->surface_index >> 16); -				ERR_CONTINUE(!mesh.is_valid()); //should be a bug - -				mesh_surface = storage->mesh_get_surface(e->instance->base, e->surface_index & 0xFFFF); - -				primitive = storage->mesh_surface_get_primitive(mesh_surface); - -				xforms_uniform_set = storage->particles_get_instance_buffer_uniform_set(e->instance->base, default_shader_rd, TRANSFORMS_UNIFORM_SET); - -			} break; -			default: { -				ERR_CONTINUE(true); //should be a bug -			} -		} +		RS::PrimitiveType primitive = surf->primitive; +		RID xforms_uniform_set = surf->owner->transforms_uniform_set;  		ShaderVersion shader_version = SHADER_VERSION_MAX; // Assigned to silence wrong -Wmaybe-initialized. -		switch (p_pass_mode) { +		switch (p_params->pass_mode) {  			case PASS_MODE_COLOR:  			case PASS_MODE_COLOR_TRANSPARENT: { -				if (e->uses_lightmap) { +				if (surf->sort.uses_lightmap) {  					shader_version = SHADER_VERSION_LIGHTMAP_COLOR_PASS; -				} else if (e->uses_forward_gi) { +				} else if (surf->sort.uses_forward_gi) {  					shader_version = SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI;  				} else {  					shader_version = SHADER_VERSION_COLOR_PASS;  				}  			} break;  			case PASS_MODE_COLOR_SPECULAR: { -				if (e->uses_lightmap) { +				if (surf->sort.uses_lightmap) {  					shader_version = SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR;  				} else {  					shader_version = SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR; @@ -1086,40 +929,37 @@ void RendererSceneRenderForward::_render_list(RenderingDevice::DrawListID p_draw  		RID vertex_array_rd;  		RID index_array_rd; -		if (mesh_surface) { -			if (e->instance->mesh_instance.is_valid()) { //skeleton and blend shape -				storage->mesh_instance_surface_get_vertex_arrays_and_format(e->instance->mesh_instance, e->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format); -			} else { -				storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format); -			} - -			if (p_screen_lod_threshold > 0.0 && storage->mesh_surface_has_lod(mesh_surface)) { -				Vector3 support_min = e->instance->transformed_aabb.get_support(-p_lod_plane.normal); -				Vector3 support_max = e->instance->transformed_aabb.get_support(p_lod_plane.normal); - -				float distance_min = p_lod_plane.distance_to(support_min); -				float distance_max = p_lod_plane.distance_to(support_max); +		//skeleton and blend shape +		if (surf->owner->mesh_instance.is_valid()) { +			storage->mesh_instance_surface_get_vertex_arrays_and_format(surf->owner->mesh_instance, surf->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format); +		} else { +			storage->mesh_surface_get_vertex_arrays_and_format(mesh_surface, pipeline->get_vertex_input_mask(), vertex_array_rd, vertex_format); +		} -				float distance = 0.0; +		if (p_params->screen_lod_threshold > 0.0 && storage->mesh_surface_has_lod(mesh_surface)) { +			//lod +			Vector3 support_min = surf->owner->transformed_aabb.get_support(-p_params->lod_plane.normal); +			Vector3 support_max = surf->owner->transformed_aabb.get_support(p_params->lod_plane.normal); -				if (distance_min * distance_max < 0.0) { -					//crossing plane -					distance = 0.0; -				} else if (distance_min >= 0.0) { -					distance = distance_min; -				} else if (distance_max <= 0.0) { -					distance = -distance_max; -				} +			float distance_min = p_params->lod_plane.distance_to(support_min); +			float distance_max = p_params->lod_plane.distance_to(support_max); -				Vector3 model_scale_vec = e->instance->transform.basis.get_scale_abs(); +			float distance = 0.0; -				float model_scale = MAX(model_scale_vec.x, MAX(model_scale_vec.y, model_scale_vec.z)); +			if (distance_min * distance_max < 0.0) { +				//crossing plane +				distance = 0.0; +			} else if (distance_min >= 0.0) { +				distance = distance_min; +			} else if (distance_max <= 0.0) { +				distance = -distance_max; +			} -				index_array_rd = storage->mesh_surface_get_index_array_with_lod(mesh_surface, model_scale * e->instance->lod_bias, distance * p_lod_distance_multiplier, p_screen_lod_threshold); +			index_array_rd = storage->mesh_surface_get_index_array_with_lod(mesh_surface, surf->owner->lod_model_scale * surf->owner->lod_bias, distance * p_params->lod_distance_multiplier, p_params->screen_lod_threshold); -			} else { -				index_array_rd = storage->mesh_surface_get_index_array(mesh_surface); -			} +		} else { +			//no lod +			index_array_rd = storage->mesh_surface_get_index_array(mesh_surface);  		}  		if (prev_vertex_array_rd != vertex_array_rd) { @@ -1134,7 +974,7 @@ void RendererSceneRenderForward::_render_list(RenderingDevice::DrawListID p_draw  			prev_index_array_rd = index_array_rd;  		} -		RID pipeline_rd = pipeline->get_render_pipeline(vertex_format, framebuffer_format, p_force_wireframe); +		RID pipeline_rd = pipeline->get_render_pipeline(vertex_format, framebuffer_format, p_params->force_wireframe);  		if (pipeline_rd != prev_pipeline_rd) {  			// checking with prev shader does not make so much sense, as @@ -1148,39 +988,89 @@ void RendererSceneRenderForward::_render_list(RenderingDevice::DrawListID p_draw  			prev_xforms_uniform_set = xforms_uniform_set;  		} -		if (material != prev_material) { +		if (material_uniform_set != prev_material_uniform_set) {  			//update uniform set -			if (material->uniform_set.is_valid()) { -				RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material->uniform_set, MATERIAL_UNIFORM_SET); +			if (material_uniform_set.is_valid()) { +				RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material_uniform_set, MATERIAL_UNIFORM_SET);  			} -			prev_material = material; +			prev_material_uniform_set = material_uniform_set;  		} -		push_constant.index = i; -		RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(PushConstant)); +		RD::get_singleton()->draw_list_set_push_constant(draw_list, &surf->owner->push_constant, sizeof(GeometryInstanceForward::PushConstant)); -		switch (e->instance->base_type) { -			case RS::INSTANCE_MESH: { -				RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid()); -			} break; -			case RS::INSTANCE_MULTIMESH: { -				uint32_t instances = storage->multimesh_get_instances_to_draw(e->instance->base); -				RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instances); -			} break; -			case RS::INSTANCE_IMMEDIATE: { -			} break; -			case RS::INSTANCE_PARTICLES: { -				uint32_t instances = storage->particles_get_amount(e->instance->base); -				RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instances); -			} break; -			default: { -				ERR_CONTINUE(true); //should be a bug -			} +		RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), surf->owner->instance_count); + +		if (p_params->pass_mode == PASS_MODE_DEPTH_MATERIAL) { +			surf->owner->push_constant.lightmap_uv_scale[0] = old_offset[0]; +			surf->owner->push_constant.lightmap_uv_scale[1] = old_offset[1];  		}  	}  } +void RendererSceneRenderForward::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) { +	//use template for faster performance (pass mode comparisons are inlined) + +	switch (p_params->pass_mode) { +		case PASS_MODE_COLOR: { +			_render_list_template<PASS_MODE_COLOR>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); +		} break; +		case PASS_MODE_COLOR_SPECULAR: { +			_render_list_template<PASS_MODE_COLOR_SPECULAR>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); +		} break; +		case PASS_MODE_COLOR_TRANSPARENT: { +			_render_list_template<PASS_MODE_COLOR_TRANSPARENT>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); +		} break; +		case PASS_MODE_SHADOW: { +			_render_list_template<PASS_MODE_SHADOW>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); +		} break; +		case PASS_MODE_SHADOW_DP: { +			_render_list_template<PASS_MODE_SHADOW_DP>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); +		} break; +		case PASS_MODE_DEPTH: { +			_render_list_template<PASS_MODE_DEPTH>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); +		} break; +		case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: { +			_render_list_template<PASS_MODE_DEPTH_NORMAL_ROUGHNESS>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); +		} break; +		case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE: { +			_render_list_template<PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); +		} break; +		case PASS_MODE_DEPTH_MATERIAL: { +			_render_list_template<PASS_MODE_DEPTH_MATERIAL>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); +		} break; +		case PASS_MODE_SDF: { +			_render_list_template<PASS_MODE_SDF>(p_draw_list, p_framebuffer_Format, p_params, p_from_element, p_to_element); +		} break; +	} +} + +void RendererSceneRenderForward::_render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params) { +	uint32_t render_total = p_params->element_count; +	uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count(); +	uint32_t render_from = p_thread * render_total / total_threads; +	uint32_t render_to = (p_thread + 1 == total_threads) ? render_total : ((p_thread + 1) * render_total / total_threads); +	_render_list(thread_draw_lists[p_thread], p_params->framebuffer_format, p_params, render_from, render_to); +} + +void RendererSceneRenderForward::_render_list_with_threads(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values, float p_clear_depth, uint32_t p_clear_stencil, const Rect2 &p_region, const Vector<RID> &p_storage_textures) { +	RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(p_framebuffer); +	p_params->framebuffer_format = fb_format; + +	if ((uint32_t)p_params->element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time +		//multi threaded +		thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count()); +		RD::get_singleton()->draw_list_begin_split(p_framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, p_storage_textures); +		RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RendererSceneRenderForward::_render_list_thread_function, p_params); +		RD::get_singleton()->draw_list_end(); +	} else { +		//single threaded +		RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, p_storage_textures); +		_render_list(draw_list, fb_format, p_params, 0, p_params->element_count); +		RD::get_singleton()->draw_list_end(); +	} +} +  void RendererSceneRenderForward::_setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers, bool p_pancake_shadows) {  	//CameraMatrix projection = p_cam_projection;  	//projection.flip_y(); // Vulkan and modern APIs use Y-Down @@ -1413,128 +1303,7 @@ void RendererSceneRenderForward::_setup_environment(RID p_environment, RID p_ren  	RD::get_singleton()->buffer_update(scene_state.uniform_buffer, 0, sizeof(SceneState::UBO), &scene_state.ubo, true);  } -void RendererSceneRenderForward::_add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi) { -	RID m_src; - -	m_src = p_instance->material_override.is_valid() ? p_instance->material_override : p_material; - -	if (unlikely(get_debug_draw_mode() != RS::VIEWPORT_DEBUG_DRAW_DISABLED)) { -		if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { -			m_src = overdraw_material; -		} else if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_LIGHTING) { -			m_src = default_material; -		} -	} - -	MaterialData *material = nullptr; - -	if (m_src.is_valid()) { -		material = (MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D); -		if (!material || !material->shader_data->valid) { -			material = nullptr; -		} -	} - -	if (!material) { -		material = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D); -		m_src = default_material; -	} - -	ERR_FAIL_COND(!material); - -	_add_geometry_with_material(p_instance, p_surface, material, m_src, p_pass_mode, p_geometry_index, p_using_sdfgi); - -	while (material->next_pass.is_valid()) { -		material = (MaterialData *)storage->material_get_data(material->next_pass, RendererStorageRD::SHADER_TYPE_3D); -		if (!material || !material->shader_data->valid) { -			break; -		} -		_add_geometry_with_material(p_instance, p_surface, material, material->next_pass, p_pass_mode, p_geometry_index, p_using_sdfgi); -	} -} - -void RendererSceneRenderForward::_add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi) { -	bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture; -	bool has_base_alpha = (p_material->shader_data->uses_alpha || has_read_screen_alpha); -	bool has_blend_alpha = p_material->shader_data->uses_blend_alpha; -	bool has_alpha = has_base_alpha || has_blend_alpha; - -	if (p_material->shader_data->uses_sss) { -		scene_state.used_sss = true; -	} - -	if (p_material->shader_data->uses_screen_texture) { -		scene_state.used_screen_texture = true; -	} - -	if (p_material->shader_data->uses_depth_texture) { -		scene_state.used_depth_texture = true; -	} - -	if (p_material->shader_data->uses_normal_texture) { -		scene_state.used_normal_texture = true; -	} - -	if (p_pass_mode != PASS_MODE_COLOR && p_pass_mode != PASS_MODE_COLOR_SPECULAR) { -		if (has_blend_alpha || has_read_screen_alpha || (has_base_alpha && !p_material->shader_data->uses_depth_pre_pass) || p_material->shader_data->depth_draw == ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED || p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_OFF) { -			//conditions in which no depth pass should be processed -			return; -		} - -		if ((p_pass_mode != PASS_MODE_DEPTH_MATERIAL && p_pass_mode != PASS_MODE_SDF) && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass) { -			//shader does not use discard and does not write a vertex position, use generic material -			if (p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_DEPTH) { -				p_material = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D); -			} else if ((p_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS || p_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE) && !p_material->shader_data->uses_normal && !p_material->shader_data->uses_roughness) { -				p_material = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D); -			} -		} - -		has_alpha = false; -	} - -	has_alpha = has_alpha || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED; - -	RenderList::Element *e = has_alpha ? render_list.add_alpha_element() : render_list.add_element(); - -	if (!e) { -		return; -	} - -	e->instance = p_instance; -	e->material = p_material; -	e->surface_index = p_surface; -	e->sort_key = 0; - -	if (e->material->last_pass != render_pass) { -		if (!RD::get_singleton()->uniform_set_is_valid(e->material->uniform_set)) { -			//uniform set no longer valid, probably a texture changed -			storage->material_force_update_textures(p_material_rid, RendererStorageRD::SHADER_TYPE_3D); -		} -		e->material->last_pass = render_pass; -		e->material->index = scene_state.current_material_index++; -		if (e->material->shader_data->last_pass != render_pass) { -			e->material->shader_data->last_pass = scene_state.current_material_index++; -			e->material->shader_data->index = scene_state.current_shader_index++; -		} -	} -	e->geometry_index = p_geometry_index; -	e->material_index = e->material->index; -	e->uses_instancing = e->instance->base_type == RS::INSTANCE_MULTIMESH; -	e->uses_lightmap = e->instance->lightmap != nullptr || !e->instance->lightmap_sh.is_empty(); -	e->uses_forward_gi = has_alpha && (e->instance->gi_probe_instances.size() || p_using_sdfgi); -	e->shader_index = e->shader_index; -	e->depth_layer = e->instance->depth_layer; -	e->priority = p_material->priority; - -	if (p_material->shader_data->uses_time) { -		RenderingServerDefault::redraw_request(); -	} -} - -void RendererSceneRenderForward::_fill_render_list(const PagedArray<InstanceBase *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi) { -	scene_state.current_shader_index = 0; -	scene_state.current_material_index = 0; +void RendererSceneRenderForward::_fill_render_list(const PagedArray<GeometryInstance *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi, bool p_using_opaque_gi) {  	scene_state.used_sss = false;  	scene_state.used_screen_texture = false;  	scene_state.used_normal_texture = false; @@ -1543,125 +1312,184 @@ void RendererSceneRenderForward::_fill_render_list(const PagedArray<InstanceBase  	Plane near_plane(p_cam_transform.origin, -p_cam_transform.basis.get_axis(Vector3::AXIS_Z));  	near_plane.d += p_cam_projection.get_z_near();  	float z_max = p_cam_projection.get_z_far() - p_cam_projection.get_z_near(); +	uint32_t lightmap_captures_used = 0; -	uint32_t geometry_index = 0; +	_update_dirty_geometry_instances(); +	render_list.clear();  	//fill list  	for (int i = 0; i < (int)p_instances.size(); i++) { -		InstanceBase *inst = p_instances[i]; +		GeometryInstanceForward *inst = static_cast<GeometryInstanceForward *>(p_instances[i]); -		inst->depth = near_plane.distance_to(inst->transform.origin); -		inst->depth_layer = CLAMP(int(inst->depth * 16 / z_max), 0, 15); +		Vector3 support_min = inst->transformed_aabb.get_support(-near_plane.normal); +		inst->depth = near_plane.distance_to(support_min); +		uint32_t depth_layer = CLAMP(int(inst->depth * 16 / z_max), 0, 15); -		//add geometry for drawing -		switch (inst->base_type) { -			case RS::INSTANCE_MESH: { -				const RID *materials = nullptr; -				uint32_t surface_count; +		uint32_t flags = inst->base_flags; //fill flags if appropriate -				materials = storage->mesh_get_surface_count_and_materials(inst->base, surface_count); -				if (!materials) { -					continue; //nothing to do -				} - -				const RID *inst_materials = inst->materials.ptr(); +		bool uses_lightmap = false; +		bool uses_gi = false; -				for (uint32_t j = 0; j < surface_count; j++) { -					RID material = inst_materials[j].is_valid() ? inst_materials[j] : materials[j]; +		if (p_pass_mode == PASS_MODE_COLOR) { +			//setup GI -					uint32_t surface_index = storage->mesh_surface_get_render_pass_index(inst->base, j, render_pass, &geometry_index); -					_add_geometry(inst, j, material, p_pass_mode, surface_index, p_using_sdfgi); +			if (inst->lightmap_instance.is_valid()) { +				int32_t lightmap_cull_index = -1; +				for (uint32_t j = 0; j < scene_state.lightmaps_used; j++) { +					if (scene_state.lightmap_ids[j] == inst->lightmap_instance) { +						lightmap_cull_index = j; +						break; +					}  				} - -				//mesh->last_pass=frame; - -			} break; - -			case RS::INSTANCE_MULTIMESH: { -				if (storage->multimesh_get_instances_to_draw(inst->base) == 0) { -					//not visible, 0 instances -					continue; +				if (lightmap_cull_index >= 0) { +					inst->push_constant.gi_offset &= 0xFFFF; +					inst->push_constant.gi_offset |= lightmap_cull_index; +					flags |= INSTANCE_DATA_FLAG_USE_LIGHTMAP; +					if (scene_state.lightmap_has_sh[lightmap_cull_index]) { +						flags |= INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP; +					} +					uses_lightmap = true; +				} else { +					inst->push_constant.gi_offset = 0xFFFFFFFF;  				} -				RID mesh = storage->multimesh_get_mesh(inst->base); -				if (!mesh.is_valid()) { -					continue; +			} else if (inst->lightmap_sh) { +				if (lightmap_captures_used < scene_state.max_lightmap_captures) { +					const Color *src_capture = inst->lightmap_sh->sh; +					LightmapCaptureData &lcd = scene_state.lightmap_captures[lightmap_captures_used]; +					for (int j = 0; j < 9; j++) { +						lcd.sh[j * 4 + 0] = src_capture[j].r; +						lcd.sh[j * 4 + 1] = src_capture[j].g; +						lcd.sh[j * 4 + 2] = src_capture[j].b; +						lcd.sh[j * 4 + 3] = src_capture[j].a; +					} +					flags |= INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE; +					inst->push_constant.gi_offset = lightmap_captures_used; +					lightmap_captures_used++; +					uses_lightmap = true;  				} -				const RID *materials = nullptr; -				uint32_t surface_count; - -				materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count); -				if (!materials) { -					continue; //nothing to do +			} else if (!low_end) { +				if (p_using_opaque_gi) { +					flags |= INSTANCE_DATA_FLAG_USE_GI_BUFFERS;  				} -				for (uint32_t j = 0; j < surface_count; j++) { -					uint32_t surface_index = storage->mesh_surface_get_multimesh_render_pass_index(mesh, j, render_pass, &geometry_index); -					_add_geometry(inst, j, materials[j], p_pass_mode, surface_index, p_using_sdfgi); -				} +				if (inst->gi_probes[0].is_valid()) { +					uint32_t probe0_index = 0xFFFF; +					uint32_t probe1_index = 0xFFFF; -			} break; -#if 0 -			case RS::INSTANCE_IMMEDIATE: { -				RasterizerStorageGLES3::Immediate *immediate = storage->immediate_owner.getornull(inst->base); -				ERR_CONTINUE(!immediate); +					for (uint32_t j = 0; j < scene_state.giprobes_used; j++) { +						if (scene_state.giprobe_ids[j] == inst->gi_probes[0]) { +							probe0_index = j; +						} else if (scene_state.giprobe_ids[j] == inst->gi_probes[1]) { +							probe1_index = j; +						} +					} -				_add_geometry(immediate, inst, nullptr, -1, p_depth_pass, p_shadow_pass); +					if (probe0_index == 0xFFFF && probe1_index != 0xFFFF) { +						//0 must always exist if a probe exists +						SWAP(probe0_index, probe1_index); +					} -			} break; -#endif -			case RS::INSTANCE_PARTICLES: { -				int draw_passes = storage->particles_get_draw_passes(inst->base); +					inst->push_constant.gi_offset = probe0_index | (probe1_index << 16); +					uses_gi = true; +				} else { +					if (p_using_sdfgi && inst->can_sdfgi) { +						flags |= INSTANCE_DATA_FLAG_USE_SDFGI; +						uses_gi = true; +					} +					inst->push_constant.gi_offset = 0xFFFFFFFF; +				} +			} +		} +		inst->push_constant.flags = flags; -				for (int j = 0; j < draw_passes; j++) { -					RID mesh = storage->particles_get_draw_pass_mesh(inst->base, j); -					if (!mesh.is_valid()) -						continue; +		GeometryInstanceSurfaceDataCache *surf = inst->surface_caches; -					const RID *materials = nullptr; -					uint32_t surface_count; +		while (surf) { +			surf->sort.uses_forward_gi = 0; +			surf->sort.uses_lightmap = 0; -					materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count); -					if (!materials) { -						continue; //nothing to do +			if (p_pass_mode == PASS_MODE_COLOR) { +				if (surf->flags & (GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH | GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) { +					render_list.add_element(surf); +				} +				if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA) { +					render_list.add_alpha_element(surf); +					if (uses_gi) { +						surf->sort.uses_forward_gi = 1;  					} +				} -					for (uint32_t k = 0; k < surface_count; k++) { -						uint32_t surface_index = storage->mesh_surface_get_particles_render_pass_index(mesh, j, render_pass, &geometry_index); -						_add_geometry(inst, (j << 16) | k, materials[j], p_pass_mode, surface_index, p_using_sdfgi); -					} +				if (uses_lightmap) { +					surf->sort.uses_lightmap = 1;  				} -			} break; +				if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_SUBSURFACE_SCATTERING) { +					scene_state.used_sss = true; +				} +				if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_SCREEN_TEXTURE) { +					scene_state.used_screen_texture = true; +				} +				if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_NORMAL_TEXTURE) { +					scene_state.used_normal_texture = true; +				} +				if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_DEPTH_TEXTURE) { +					scene_state.used_depth_texture = true; +				} -			default: { +			} else if (p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) { +				if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_SHADOW) { +					render_list.add_element(surf); +				} +			} else { +				if (surf->flags & (GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH | GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE)) { +					render_list.add_element(surf); +				}  			} + +			surf->sort.depth_layer = depth_layer; + +			surf = surf->next;  		}  	} + +	if (lightmap_captures_used) { +		RD::get_singleton()->buffer_update(scene_state.lightmap_capture_buffer, 0, sizeof(LightmapCaptureData) * lightmap_captures_used, scene_state.lightmap_captures, true); +	}  } -void RendererSceneRenderForward::_setup_lightmaps(const PagedArray<InstanceBase *> &p_lightmaps, const Transform &p_cam_transform) { -	uint32_t lightmaps_used = 0; +void RendererSceneRenderForward::_setup_giprobes(const PagedArray<RID> &p_giprobes) { +	scene_state.giprobes_used = MIN(p_giprobes.size(), uint32_t(MAX_GI_PROBES)); +	for (uint32_t i = 0; i < scene_state.giprobes_used; i++) { +		scene_state.giprobe_ids[i] = p_giprobes[i]; +	} +} + +void RendererSceneRenderForward::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform &p_cam_transform) { +	scene_state.lightmaps_used = 0;  	for (int i = 0; i < (int)p_lightmaps.size(); i++) {  		if (i >= (int)scene_state.max_lightmaps) {  			break;  		} -		InstanceBase *lm = p_lightmaps[i]; -		Basis to_lm = lm->transform.basis.inverse() * p_cam_transform.basis; +		RID lightmap = lightmap_instance_get_lightmap(p_lightmaps[i]); + +		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); -		lm->lightmap_cull_index = i; -		lightmaps_used++; +		scene_state.lightmap_ids[i] = p_lightmaps[i]; +		scene_state.lightmap_has_sh[i] = storage->lightmap_uses_spherical_harmonics(lightmap); + +		scene_state.lightmaps_used++;  	} -	if (lightmaps_used > 0) { -		RD::get_singleton()->buffer_update(scene_state.lightmap_buffer, 0, sizeof(LightmapData) * lightmaps_used, scene_state.lightmaps, true); +	if (scene_state.lightmaps_used > 0) { +		RD::get_singleton()->buffer_update(scene_state.lightmap_buffer, 0, sizeof(LightmapData) * scene_state.lightmaps_used, scene_state.lightmaps, true);  	}  } -void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_screen_lod_threshold) { +void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_screen_lod_threshold) {  	RenderBufferDataForward *render_buffer = nullptr;  	if (p_render_buffer.is_valid()) {  		render_buffer = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffer); @@ -1784,12 +1612,12 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf  	}  	_setup_lightmaps(p_lightmaps, p_cam_transform); +	_setup_giprobes(p_gi_probes);  	_setup_environment(p_environment, p_render_buffer, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false);  	_update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example) -	render_list.clear(); -	_fill_render_list(p_instances, PASS_MODE_COLOR, p_cam_projection, p_cam_transform, using_sdfgi); +	_fill_render_list(p_instances, PASS_MODE_COLOR, p_cam_projection, p_cam_transform, using_sdfgi, using_sdfgi || using_giprobe);  	bool using_sss = !low_end && render_buffer && scene_state.used_sss && sub_surface_scattering_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED; @@ -1873,8 +1701,6 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf  	render_list.sort_by_key(false); -	_fill_instances(render_list.elements, render_list.element_count, false, false, using_sdfgi || using_giprobe); -  	bool debug_giprobes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_ALBEDO || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION;  	bool debug_sdfgi_probes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SDFGI_PROBES; @@ -1885,12 +1711,11 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf  	if (depth_pre_pass) { //depth pre pass  		RENDER_TIMESTAMP("Render Depth Pre-Pass"); -		RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>()); +		RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());  		bool finish_depth = using_ssao || using_sdfgi || using_giprobe; -		RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, depth_pass_clear); -		_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(depth_framebuffer), render_list.elements, render_list.element_count, false, depth_pass_mode, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold); -		RD::get_singleton()->draw_list_end(); +		RenderListParameters render_list_params(render_list.elements, render_list.element_count, false, depth_pass_mode, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold); +		_render_list_with_threads(&render_list_params, depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, depth_pass_clear);  		if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {  			RENDER_TIMESTAMP("Resolve Depth Pre-Pass"); @@ -1917,7 +1742,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf  	RENDER_TIMESTAMP("Render Opaque Pass"); -	RID rp_uniform_set = _setup_render_pass_uniform_set(p_render_buffer, radiance_texture, p_shadow_atlas, p_reflection_atlas, p_gi_probes); +	RID rp_uniform_set = _setup_render_pass_uniform_set(p_render_buffer, radiance_texture, p_shadow_atlas, p_reflection_atlas, p_gi_probes, p_lightmaps);  	bool can_continue_color = !scene_state.used_screen_texture && !using_ssr && !using_sss;  	bool can_continue_depth = !scene_state.used_depth_texture && !using_ssr && !using_sss; @@ -1938,13 +1763,13 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf  		}  		RID framebuffer = using_separate_specular ? opaque_specular_framebuffer : opaque_framebuffer; -		RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CONTINUE) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0); -		_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(framebuffer), render_list.elements, render_list.element_count, false, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold); -		RD::get_singleton()->draw_list_end(); +		RenderListParameters render_list_params(render_list.elements, render_list.element_count, false, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold); + +		_render_list_with_threads(&render_list_params, framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CONTINUE) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);  		if (will_continue_color && using_separate_specular) {  			// close the specular framebuffer, as it's no longer used -			draw_list = RD::get_singleton()->draw_list_begin(render_buffer->specular_only_fb, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_CONTINUE); +			RD::get_singleton()->draw_list_begin(render_buffer->specular_only_fb, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_CONTINUE);  			RD::get_singleton()->draw_list_end();  		}  	} @@ -2023,12 +1848,9 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf  	render_list.sort_by_reverse_depth_and_priority(true); -	_fill_instances(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, using_sdfgi); -  	{ -		RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(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); -		_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(alpha_framebuffer), &render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, PASS_MODE_COLOR, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold); -		RD::get_singleton()->draw_list_end(); +		RenderListParameters render_list_params(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, PASS_MODE_COLOR, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), lod_camera_plane, lod_distance_multiplier, p_screen_lod_threshold); +		_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);  	}  	if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) { @@ -2036,7 +1858,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf  	}  } -void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, const PagedArray<InstanceBase *> &p_instances, const CameraMatrix &p_projection, const Transform &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, float p_lod_distance_multiplier, float p_screen_lod_threshold) { +void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &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, float p_lod_distance_multiplier, float p_screen_lod_threshold) {  	RENDER_TIMESTAMP("Setup Rendering Shadow");  	_update_render_base_uniform_set(); @@ -2051,29 +1873,24 @@ void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, const PagedAr  		p_screen_lod_threshold = 0.0;  	} -	render_list.clear(); -  	PassMode pass_mode = p_use_dp ? PASS_MODE_SHADOW_DP : PASS_MODE_SHADOW;  	_fill_render_list(p_instances, pass_mode, p_projection, p_transform); -	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>()); +	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());  	RENDER_TIMESTAMP("Render Shadow");  	render_list.sort_by_key(false); -	_fill_instances(render_list.elements, render_list.element_count, true); -  	{  		//regular forward for now -		RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ); -		_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, p_use_dp_flip, pass_mode, true, rp_uniform_set, false, Vector2(), p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold); -		RD::get_singleton()->draw_list_end(); +		RenderListParameters render_list_params(render_list.elements, render_list.element_count, p_use_dp_flip, pass_mode, true, rp_uniform_set, false, Vector2(), p_camera_plane, p_lod_distance_multiplier, p_screen_lod_threshold); +		_render_list_with_threads(&render_list_params, p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ);  	}  } -void RendererSceneRenderForward::_render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<InstanceBase *> &p_instances) { +void RendererSceneRenderForward::_render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) {  	RENDER_TIMESTAMP("Setup Render Collider Heightfield");  	_update_render_base_uniform_set(); @@ -2084,29 +1901,24 @@ void RendererSceneRenderForward::_render_particle_collider_heightfield(RID p_fb,  	_setup_environment(RID(), RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), RID(), true, Color(), 0, p_cam_projection.get_z_far(), false, false); -	render_list.clear(); -  	PassMode pass_mode = PASS_MODE_SHADOW;  	_fill_render_list(p_instances, pass_mode, p_cam_projection, p_cam_transform); -	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>()); +	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());  	RENDER_TIMESTAMP("Render Collider Heightield");  	render_list.sort_by_key(false); -	_fill_instances(render_list.elements, render_list.element_count, true); -  	{  		//regular forward for now -		RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ); -		_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_fb), render_list.elements, render_list.element_count, false, pass_mode, true, rp_uniform_set); -		RD::get_singleton()->draw_list_end(); +		RenderListParameters render_list_params(render_list.elements, render_list.element_count, false, pass_mode, true, rp_uniform_set); +		_render_list_with_threads(&render_list_params, p_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ);  	}  } -void RendererSceneRenderForward::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { +void RendererSceneRenderForward::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {  	RENDER_TIMESTAMP("Setup Rendering Material");  	_update_render_base_uniform_set(); @@ -2118,20 +1930,17 @@ void RendererSceneRenderForward::_render_material(const Transform &p_cam_transfo  	_setup_environment(RID(), RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0); -	render_list.clear(); -  	PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL;  	_fill_render_list(p_instances, pass_mode, p_cam_projection, p_cam_transform); -	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>()); +	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());  	RENDER_TIMESTAMP("Render Material");  	render_list.sort_by_key(false); -	_fill_instances(render_list.elements, render_list.element_count, true); -  	{ +		RenderListParameters render_list_params(render_list.elements, render_list.element_count, true, pass_mode, true, rp_uniform_set);  		//regular forward for now  		Vector<Color> clear;  		clear.push_back(Color(0, 0, 0, 0)); @@ -2140,12 +1949,12 @@ void RendererSceneRenderForward::_render_material(const Transform &p_cam_transfo  		clear.push_back(Color(0, 0, 0, 0));  		clear.push_back(Color(0, 0, 0, 0));  		RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, clear, 1.0, 0, p_region); -		_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, true, pass_mode, true, rp_uniform_set); +		_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), &render_list_params, 0, render_list_params.element_count);  		RD::get_singleton()->draw_list_end();  	}  } -void RendererSceneRenderForward::_render_uv2(const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { +void RendererSceneRenderForward::_render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {  	RENDER_TIMESTAMP("Setup Rendering UV2");  	_update_render_base_uniform_set(); @@ -2157,20 +1966,17 @@ void RendererSceneRenderForward::_render_uv2(const PagedArray<InstanceBase *> &p  	_setup_environment(RID(), RID(), CameraMatrix(), Transform(), RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0); -	render_list.clear(); -  	PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL;  	_fill_render_list(p_instances, pass_mode, CameraMatrix(), Transform()); -	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>()); +	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), PagedArray<RID>(), PagedArray<RID>());  	RENDER_TIMESTAMP("Render Material");  	render_list.sort_by_key(false); -	_fill_instances(render_list.elements, render_list.element_count, true); -  	{ +		RenderListParameters render_list_params(render_list.elements, render_list.element_count, true, pass_mode, true, rp_uniform_set, true);  		//regular forward for now  		Vector<Color> clear;  		clear.push_back(Color(0, 0, 0, 0)); @@ -2198,15 +2004,17 @@ void RendererSceneRenderForward::_render_uv2(const PagedArray<InstanceBase *> &p  			Vector2 ofs = uv_offsets[i];  			ofs.x /= p_region.size.width;  			ofs.y /= p_region.size.height; -			_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, true, pass_mode, true, rp_uniform_set, true, ofs); //first wireframe, for pseudo conservative +			render_list_params.uv_offset = ofs; +			_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), &render_list_params, 0, render_list_params.element_count); //first wireframe, for pseudo conservative  		} -		_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, true, pass_mode, true, rp_uniform_set, false); //second regular triangles +		render_list_params.uv_offset = Vector2(); +		_render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), &render_list_params, 0, render_list_params.element_count); //second regular triangles  		RD::get_singleton()->draw_list_end();  	}  } -void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<InstanceBase *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) { +void RendererSceneRenderForward::_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) {  	RENDER_TIMESTAMP("Render SDFGI");  	_update_render_base_uniform_set(); @@ -2215,12 +2023,10 @@ void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vecto  	ERR_FAIL_COND(!render_buffer);  	render_pass++; -	render_list.clear();  	PassMode pass_mode = PASS_MODE_SDF;  	_fill_render_list(p_instances, pass_mode, CameraMatrix(), Transform());  	render_list.sort_by_key(false); -	_fill_instances(render_list.elements, render_list.element_count, true);  	RID rp_uniform_set = _setup_sdfgi_render_pass_uniform_set(p_albedo_texture, p_emission_texture, p_emission_aniso_texture, p_geom_facing_texture); @@ -2281,9 +2087,8 @@ void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vecto  			E = sdfgi_framebuffer_size_cache.insert(fb_size, fb);  		} -		RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(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(draw_list, RD::get_singleton()->framebuffer_get_format(E->get()), render_list.elements, render_list.element_count, true, pass_mode, true, rp_uniform_set, false); //second regular triangles -		RD::get_singleton()->draw_list_end(); +		RenderListParameters render_list_params(render_list.elements, render_list.element_count, true, pass_mode, true, 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);  	}  } @@ -2340,13 +2145,6 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {  			u.ids.push_back(scene_state.uniform_buffer);  			uniforms.push_back(u);  		} -		{ -			RD::Uniform u; -			u.binding = 4; -			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; -			u.ids.push_back(scene_state.instance_buffer); -			uniforms.push_back(u); -		}  		{  			RD::Uniform u; @@ -2380,20 +2178,13 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {  		{  			RD::Uniform u;  			u.binding = 11; -			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; -			u.ids = storage->lightmap_array_get_textures(); -			uniforms.push_back(u); -		} -		{ -			RD::Uniform u; -			u.binding = 12;  			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;  			u.ids.push_back(scene_state.lightmap_capture_buffer);  			uniforms.push_back(u);  		}  		{  			RD::Uniform u; -			u.binding = 13; +			u.binding = 12;  			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  			RID decal_atlas = storage->decal_atlas_get_texture();  			u.ids.push_back(decal_atlas); @@ -2401,7 +2192,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {  		}  		{  			RD::Uniform u; -			u.binding = 14; +			u.binding = 13;  			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  			RID decal_atlas = storage->decal_atlas_get_texture_srgb();  			u.ids.push_back(decal_atlas); @@ -2409,7 +2200,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {  		}  		{  			RD::Uniform u; -			u.binding = 15; +			u.binding = 14;  			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;  			u.ids.push_back(get_decal_buffer());  			uniforms.push_back(u); @@ -2417,14 +2208,14 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {  		{  			RD::Uniform u; -			u.binding = 16; +			u.binding = 15;  			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  			u.ids.push_back(get_cluster_builder_texture());  			uniforms.push_back(u);  		}  		{  			RD::Uniform u; -			u.binding = 17; +			u.binding = 16;  			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;  			u.ids.push_back(get_cluster_builder_indices_buffer());  			uniforms.push_back(u); @@ -2432,7 +2223,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {  		{  			RD::Uniform u; -			u.binding = 18; +			u.binding = 17;  			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  			if (directional_shadow_get_texture().is_valid()) {  				u.ids.push_back(directional_shadow_get_texture()); @@ -2445,7 +2236,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {  		{  			RD::Uniform u;  			u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER; -			u.binding = 19; +			u.binding = 18;  			u.ids.push_back(storage->global_variables_get_storage_buffer());  			uniforms.push_back(u);  		} @@ -2453,7 +2244,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {  		if (!low_end) {  			RD::Uniform u;  			u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; -			u.binding = 20; +			u.binding = 19;  			u.ids.push_back(sdfgi_get_ubo());  			uniforms.push_back(u);  		} @@ -2462,7 +2253,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {  	}  } -RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, const PagedArray<RID> &p_gi_probes) { +RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps) {  	if (render_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_pass_uniform_set)) {  		RD::get_singleton()->free(render_pass_uniform_set);  	} @@ -2517,11 +2308,29 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff  		u.ids.push_back(texture);  		uniforms.push_back(u);  	} -  	{  		RD::Uniform u;  		u.binding = 3;  		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; +		u.ids.resize(scene_state.max_lightmaps); +		RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); +		for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) { +			if (i < p_lightmaps.size()) { +				RID base = lightmap_instance_get_lightmap(p_lightmaps[i]); +				RID texture = storage->lightmap_get_texture(base); +				RID rd_texture = storage->texture_get_rd_texture(texture); +				u.ids.write[i] = rd_texture; +			} else { +				u.ids.write[i] = default_tex; +			} +		} + +		uniforms.push_back(u); +	} +	{ +		RD::Uniform u; +		u.binding = 4; +		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  		u.ids.resize(MAX_GI_PROBES);  		RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);  		for (int i = 0; i < MAX_GI_PROBES; i++) { @@ -2541,7 +2350,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff  	{  		RD::Uniform u; -		u.binding = 4; +		u.binding = 5;  		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  		RID texture = (false && rb && rb->depth.is_valid()) ? rb->depth : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE);  		u.ids.push_back(texture); @@ -2549,7 +2358,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff  	}  	{  		RD::Uniform u; -		u.binding = 5; +		u.binding = 6;  		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  		RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_buffers) : RID();  		RID texture = bbt.is_valid() ? bbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); @@ -2559,7 +2368,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff  	if (!low_end) {  		{  			RD::Uniform u; -			u.binding = 6; +			u.binding = 7;  			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  			RID texture = rb && rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_NORMAL);  			u.ids.push_back(texture); @@ -2568,7 +2377,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff  		{  			RD::Uniform u; -			u.binding = 7; +			u.binding = 8;  			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  			RID aot = rb ? render_buffers_get_ao_texture(p_render_buffers) : RID();  			RID texture = aot.is_valid() ? aot : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); @@ -2578,7 +2387,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff  		{  			RD::Uniform u; -			u.binding = 8; +			u.binding = 9;  			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  			RID texture = rb && rb->ambient_buffer.is_valid() ? rb->ambient_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);  			u.ids.push_back(texture); @@ -2587,7 +2396,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff  		{  			RD::Uniform u; -			u.binding = 9; +			u.binding = 10;  			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  			RID texture = rb && rb->reflection_buffer.is_valid() ? rb->reflection_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK);  			u.ids.push_back(texture); @@ -2595,7 +2404,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff  		}  		{  			RD::Uniform u; -			u.binding = 10; +			u.binding = 11;  			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  			RID t;  			if (rb && render_buffers_is_sdfgi_enabled(p_render_buffers)) { @@ -2608,7 +2417,7 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff  		}  		{  			RD::Uniform u; -			u.binding = 11; +			u.binding = 12;  			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  			if (rb && render_buffers_is_sdfgi_enabled(p_render_buffers)) {  				u.ids.push_back(render_buffers_get_sdfgi_occlusion_texture(p_render_buffers)); @@ -2619,14 +2428,14 @@ RID RendererSceneRenderForward::_setup_render_pass_uniform_set(RID p_render_buff  		}  		{  			RD::Uniform u; -			u.binding = 12; +			u.binding = 13;  			u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;  			u.ids.push_back(rb ? render_buffers_get_gi_probe_buffer(p_render_buffers) : render_buffers_get_default_gi_probe_buffer());  			uniforms.push_back(u);  		}  		{  			RD::Uniform u; -			u.binding = 13; +			u.binding = 14;  			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  			RID vfog = RID();  			if (rb && render_buffers_has_volumetric_fog(p_render_buffers)) { @@ -2684,10 +2493,24 @@ RID RendererSceneRenderForward::_setup_sdfgi_render_pass_uniform_set(RID p_albed  	}  	{ -		// No GIProbes +		// No Lightmaps  		RD::Uniform u;  		u.binding = 3;  		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; +		u.ids.resize(scene_state.max_lightmaps); +		RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); +		for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) { +			u.ids.write[i] = default_tex; +		} + +		uniforms.push_back(u); +	} + +	{ +		// No GIProbes +		RD::Uniform u; +		u.binding = 4; +		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  		u.ids.resize(MAX_GI_PROBES);  		RID default_tex = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE);  		for (int i = 0; i < MAX_GI_PROBES; i++) { @@ -2701,28 +2524,28 @@ RID RendererSceneRenderForward::_setup_sdfgi_render_pass_uniform_set(RID p_albed  	{  		RD::Uniform u;  		u.uniform_type = RD::UNIFORM_TYPE_IMAGE; -		u.binding = 4; +		u.binding = 5;  		u.ids.push_back(p_albedo_texture);  		uniforms.push_back(u);  	}  	{  		RD::Uniform u;  		u.uniform_type = RD::UNIFORM_TYPE_IMAGE; -		u.binding = 5; +		u.binding = 6;  		u.ids.push_back(p_emission_texture);  		uniforms.push_back(u);  	}  	{  		RD::Uniform u;  		u.uniform_type = RD::UNIFORM_TYPE_IMAGE; -		u.binding = 6; +		u.binding = 7;  		u.ids.push_back(p_emission_aniso_texture);  		uniforms.push_back(u);  	}  	{  		RD::Uniform u;  		u.uniform_type = RD::UNIFORM_TYPE_IMAGE; -		u.binding = 7; +		u.binding = 8;  		u.ids.push_back(p_geom_facing_texture);  		uniforms.push_back(u);  	} @@ -2765,6 +2588,534 @@ void RendererSceneRenderForward::set_time(double p_time, double p_step) {  	RendererSceneRenderRD::set_time(p_time, p_step);  } +void RendererSceneRenderForward::_geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance) { +	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +	if (ginstance->dirty_list_element.in_list()) { +		return; +	} + +	//clear surface caches +	GeometryInstanceSurfaceDataCache *surf = ginstance->surface_caches; + +	while (surf) { +		GeometryInstanceSurfaceDataCache *next = surf->next; +		geometry_instance_surface_alloc.free(surf); +		surf = next; +	} + +	ginstance->surface_caches = nullptr; + +	geometry_instance_dirty_list.add(&ginstance->dirty_list_element); +} + +void RendererSceneRenderForward::_geometry_instance_add_surface_with_material(GeometryInstanceForward *ginstance, uint32_t p_surface, MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) { +	bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture; +	bool has_base_alpha = (p_material->shader_data->uses_alpha || has_read_screen_alpha); +	bool has_blend_alpha = p_material->shader_data->uses_blend_alpha; +	bool has_alpha = has_base_alpha || has_blend_alpha; + +	uint32_t flags = 0; + +	if (p_material->shader_data->uses_sss) { +		flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SUBSURFACE_SCATTERING; +	} + +	if (p_material->shader_data->uses_screen_texture) { +		flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SCREEN_TEXTURE; +	} + +	if (p_material->shader_data->uses_depth_texture) { +		flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_DEPTH_TEXTURE; +	} + +	if (p_material->shader_data->uses_normal_texture) { +		flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_NORMAL_TEXTURE; +	} + +	if (ginstance->data->cast_double_sided_shaodows) { +		flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_DOUBLE_SIDED_SHADOWS; +	} + +	if (has_alpha || has_read_screen_alpha || p_material->shader_data->depth_draw == ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED) { +		//material is only meant for alpha pass +		flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_ALPHA; +		if (p_material->shader_data->uses_depth_pre_pass && !(p_material->shader_data->depth_draw == ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED)) { +			flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH; +			flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_SHADOW; +		} +	} else { +		flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_OPAQUE; +		flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_DEPTH; +		flags |= GeometryInstanceSurfaceDataCache::FLAG_PASS_SHADOW; +	} + +	MaterialData *material_shadow = nullptr; +	//void *surface_shadow = nullptr; +	if (!p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass) { +		flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL; +		material_shadow = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D); +	} else { +		material_shadow = p_material; +	} + +	GeometryInstanceSurfaceDataCache *sdcache = geometry_instance_surface_alloc.alloc(); + +	sdcache->flags = flags; + +	sdcache->shader = p_material->shader_data; +	sdcache->material_uniform_set = p_material->uniform_set; +	sdcache->surface = storage->mesh_get_surface(p_mesh, p_surface); +	sdcache->primitive = storage->mesh_surface_get_primitive(sdcache->surface); +	sdcache->surface_index = p_surface; + +	if (ginstance->data->dirty_dependencies) { +		storage->base_update_dependency(p_mesh, &ginstance->data->dependency_tracker); +	} + +	//shadow +	sdcache->shader_shadow = material_shadow->shader_data; +	sdcache->material_uniform_set_shadow = material_shadow->uniform_set; +	sdcache->surface_shadow = sdcache->surface; //when adding special shadow meshes, will use this + +	sdcache->owner = ginstance; + +	sdcache->next = ginstance->surface_caches; +	ginstance->surface_caches = sdcache; + +	//sortkey + +	sdcache->sort.sort_key1 = 0; +	sdcache->sort.sort_key2 = 0; + +	sdcache->sort.surface_type = ginstance->data->base_type; +	sdcache->sort.material_id = p_material_id; +	sdcache->sort.shader_id = p_shader_id; +	sdcache->sort.geometry_id = p_mesh.get_local_index(); +	sdcache->sort.uses_forward_gi = ginstance->can_sdfgi; +	sdcache->sort.priority = p_material->priority; +} + +void RendererSceneRenderForward::_geometry_instance_add_surface(GeometryInstanceForward *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) { +	RID m_src; + +	m_src = ginstance->data->material_override.is_valid() ? ginstance->data->material_override : p_material; + +	MaterialData *material = nullptr; + +	if (m_src.is_valid()) { +		material = (MaterialData *)storage->material_get_data(m_src, RendererStorageRD::SHADER_TYPE_3D); +		if (!material || !material->shader_data->valid) { +			material = nullptr; +		} +	} + +	if (material) { +		if (ginstance->data->dirty_dependencies) { +			storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker); +		} +	} else { +		material = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D); +		m_src = default_material; +	} + +	ERR_FAIL_COND(!material); + +	_geometry_instance_add_surface_with_material(ginstance, p_surface, material, m_src.get_local_index(), storage->material_get_shader_id(m_src), p_mesh); + +	while (material->next_pass.is_valid()) { +		RID next_pass = material->next_pass; +		material = (MaterialData *)storage->material_get_data(next_pass, RendererStorageRD::SHADER_TYPE_3D); +		if (!material || !material->shader_data->valid) { +			break; +		} +		if (ginstance->data->dirty_dependencies) { +			storage->material_update_dependency(next_pass, &ginstance->data->dependency_tracker); +		} +		_geometry_instance_add_surface_with_material(ginstance, p_surface, material, next_pass.get_local_index(), storage->material_get_shader_id(next_pass), p_mesh); +	} +} + +void RendererSceneRenderForward::_geometry_instance_update(GeometryInstance *p_geometry_instance) { +	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); + +	if (ginstance->data->dirty_dependencies) { +		ginstance->data->dependency_tracker.update_begin(); +	} + +	//add geometry for drawing +	switch (ginstance->data->base_type) { +		case RS::INSTANCE_MESH: { +			const RID *materials = nullptr; +			uint32_t surface_count; +			RID mesh = ginstance->data->base; + +			materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count); +			if (materials) { +				//if no materials, no surfaces. +				const RID *inst_materials = ginstance->data->surface_materials.ptr(); +				uint32_t surf_mat_count = ginstance->data->surface_materials.size(); + +				for (uint32_t j = 0; j < surface_count; j++) { +					RID material = (j < surf_mat_count && inst_materials[j].is_valid()) ? inst_materials[j] : materials[j]; +					_geometry_instance_add_surface(ginstance, j, material, mesh); +				} +			} + +			ginstance->instance_count = 1; + +		} break; + +		case RS::INSTANCE_MULTIMESH: { +			RID mesh = storage->multimesh_get_mesh(ginstance->data->base); +			if (mesh.is_valid()) { +				const RID *materials = nullptr; +				uint32_t surface_count; + +				materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count); +				if (materials) { +					for (uint32_t j = 0; j < surface_count; j++) { +						_geometry_instance_add_surface(ginstance, j, materials[j], mesh); +					} +				} + +				ginstance->instance_count = storage->multimesh_get_instances_to_draw(ginstance->data->base); +			} + +		} break; +#if 0 +		case RS::INSTANCE_IMMEDIATE: { +			RasterizerStorageGLES3::Immediate *immediate = storage->immediate_owner.getornull(inst->base); +			ERR_CONTINUE(!immediate); + +			_add_geometry(immediate, inst, nullptr, -1, p_depth_pass, p_shadow_pass); + +		} break; +#endif +		case RS::INSTANCE_PARTICLES: { +			int draw_passes = storage->particles_get_draw_passes(ginstance->data->base); + +			for (int j = 0; j < draw_passes; j++) { +				RID mesh = storage->particles_get_draw_pass_mesh(ginstance->data->base, j); +				if (!mesh.is_valid()) +					continue; + +				const RID *materials = nullptr; +				uint32_t surface_count; + +				materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count); +				if (materials) { +					for (uint32_t k = 0; k < surface_count; k++) { +						_geometry_instance_add_surface(ginstance, k, materials[k], mesh); +					} +				} +			} + +			ginstance->instance_count = storage->particles_get_amount(ginstance->data->base); + +		} break; + +		default: { +		} +	} + +	//Fill push constant + +	ginstance->push_constant.instance_uniforms_ofs = ginstance->data->shader_parameters_offset >= 0 ? ginstance->data->shader_parameters_offset : 0; +	ginstance->push_constant.layer_mask = ginstance->data->layer_mask; +	ginstance->push_constant.flags = 0; +	ginstance->push_constant.gi_offset = 0xFFFFFFFF; //disabled + +	bool store_transform = true; + +	if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) { +		ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH; +		uint32_t stride; +		if (storage->multimesh_get_transform_format(ginstance->data->base) == RS::MULTIMESH_TRANSFORM_2D) { +			ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D; +			stride = 2; +		} else { +			stride = 3; +		} +		if (storage->multimesh_uses_colors(ginstance->data->base)) { +			ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR; +			stride += 1; +		} +		if (storage->multimesh_uses_custom_data(ginstance->data->base)) { +			ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA; +			stride += 1; +		} + +		ginstance->base_flags |= (stride << INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT); +		ginstance->transforms_uniform_set = storage->multimesh_get_3d_uniform_set(ginstance->data->base, default_shader_rd, TRANSFORMS_UNIFORM_SET); + +	} else if (ginstance->data->base_type == RS::INSTANCE_PARTICLES) { +		ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH; +		uint32_t stride; +		if (false) { // 2D particles +			ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D; +			stride = 2; +		} else { +			stride = 3; +		} + +		ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR; +		stride += 1; + +		ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA; +		stride += 1; + +		ginstance->base_flags |= (stride << INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT); + +		if (!storage->particles_is_using_local_coords(ginstance->data->base)) { +			store_transform = false; +		} +		ginstance->transforms_uniform_set = storage->particles_get_instance_buffer_uniform_set(ginstance->data->base, default_shader_rd, TRANSFORMS_UNIFORM_SET); + +	} else if (ginstance->data->base_type == RS::INSTANCE_MESH) { +		if (storage->skeleton_is_valid(ginstance->data->skeleton)) { +			ginstance->base_flags |= INSTANCE_DATA_FLAG_SKELETON; +			ginstance->transforms_uniform_set = storage->skeleton_get_3d_uniform_set(ginstance->data->skeleton, default_shader_rd, TRANSFORMS_UNIFORM_SET); +			if (ginstance->data->dirty_dependencies) { +				storage->skeleton_update_dependency(ginstance->data->skeleton, &ginstance->data->dependency_tracker); +			} +		} +	} + +	if (store_transform) { +		RendererStorageRD::store_transform(ginstance->data->transform, ginstance->push_constant.transform); +	} else { +		RendererStorageRD::store_transform(Transform(), ginstance->push_constant.transform); +	} + +	ginstance->can_sdfgi = false; + +	if (lightmap_instance_is_valid(ginstance->lightmap_instance)) { +		ginstance->push_constant.gi_offset = ginstance->data->lightmap_slice_index << 16; +		ginstance->push_constant.lightmap_uv_scale[0] = ginstance->data->lightmap_uv_scale.position.x; +		ginstance->push_constant.lightmap_uv_scale[1] = ginstance->data->lightmap_uv_scale.position.y; +		ginstance->push_constant.lightmap_uv_scale[2] = ginstance->data->lightmap_uv_scale.size.width; +		ginstance->push_constant.lightmap_uv_scale[3] = ginstance->data->lightmap_uv_scale.size.height; +	} else if (!low_end) { +		if (ginstance->gi_probes[0].is_null() && (ginstance->data->use_baked_light || ginstance->data->use_dynamic_gi)) { +			ginstance->can_sdfgi = true; +		} +	} + +	if (ginstance->data->dirty_dependencies) { +		ginstance->data->dependency_tracker.update_end(); +		ginstance->data->dirty_dependencies = false; +	} + +	ginstance->dirty_list_element.remove_from_list(); +} + +void RendererSceneRenderForward::_update_dirty_geometry_instances() { +	while (geometry_instance_dirty_list.first()) { +		_geometry_instance_update(geometry_instance_dirty_list.first()->self()); +	} +} + +void RendererSceneRenderForward::_geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker) { +	switch (p_notification) { +		case RendererStorage::DEPENDENCY_CHANGED_MATERIAL: +		case RendererStorage::DEPENDENCY_CHANGED_MESH: +		case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH: +		case RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA: { +			static_cast<RendererSceneRenderForward *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata)); +		} break; +		case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: { +			GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_tracker->userdata); +			if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) { +				ginstance->instance_count = static_cast<RendererSceneRenderForward *>(singleton)->storage->multimesh_get_instances_to_draw(ginstance->data->base); +			} +		} break; +		default: { +			//rest of notifications of no interest +		} break; +	} +} +void RendererSceneRenderForward::_geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker) { +	static_cast<RendererSceneRenderForward *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata)); +} + +RendererSceneRender::GeometryInstance *RendererSceneRenderForward::geometry_instance_create(RID p_base) { +	RS::InstanceType type = storage->get_base_type(p_base); +	ERR_FAIL_COND_V(!((1 << type) & RS::INSTANCE_GEOMETRY_MASK), nullptr); + +	GeometryInstanceForward *ginstance = geometry_instance_alloc.alloc(); +	ginstance->data = memnew(GeometryInstanceForward::Data); + +	ginstance->data->base = p_base; +	ginstance->data->base_type = type; +	ginstance->data->dependency_tracker.userdata = ginstance; +	ginstance->data->dependency_tracker.changed_callback = _geometry_instance_dependency_changed; +	ginstance->data->dependency_tracker.deleted_callback = _geometry_instance_dependency_deleted; + +	_geometry_instance_mark_dirty(ginstance); + +	return ginstance; +} +void RendererSceneRenderForward::geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) { +	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +	ERR_FAIL_COND(!ginstance); +	ginstance->data->skeleton = p_skeleton; +	_geometry_instance_mark_dirty(ginstance); +	ginstance->data->dirty_dependencies = true; +} +void RendererSceneRenderForward::geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) { +	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +	ERR_FAIL_COND(!ginstance); +	ginstance->data->material_override = p_override; +	_geometry_instance_mark_dirty(ginstance); +	ginstance->data->dirty_dependencies = true; +} +void RendererSceneRenderForward::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) { +	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +	ERR_FAIL_COND(!ginstance); +	ginstance->data->surface_materials = p_materials; +	_geometry_instance_mark_dirty(ginstance); +	ginstance->data->dirty_dependencies = true; +} +void RendererSceneRenderForward::geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) { +	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +	ERR_FAIL_COND(!ginstance); +	ginstance->mesh_instance = p_mesh_instance; +	_geometry_instance_mark_dirty(ginstance); +} +void RendererSceneRenderForward::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) { +	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +	ERR_FAIL_COND(!ginstance); +	RendererStorageRD::store_transform(p_transform, ginstance->push_constant.transform); +	ginstance->data->transform = p_transform; +	ginstance->mirror = p_transform.basis.determinant() < 0; +	ginstance->data->aabb = p_aabb; +	ginstance->transformed_aabb = p_transformed_aabb; + +	Vector3 model_scale_vec = p_transform.basis.get_scale_abs(); +	// handle non uniform scale here + +	float max_scale = MAX(model_scale_vec.x, MAX(model_scale_vec.y, model_scale_vec.z)); +	float min_scale = MIN(model_scale_vec.x, MIN(model_scale_vec.y, model_scale_vec.z)); +	ginstance->non_uniform_scale = max_scale >= 0.0 && (min_scale / max_scale) < 0.9; + +	ginstance->lod_model_scale = max_scale; +} +void RendererSceneRenderForward::geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) { +	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +	ERR_FAIL_COND(!ginstance); +	ginstance->lod_bias = p_lod_bias; +} +void RendererSceneRenderForward::geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) { +	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +	ERR_FAIL_COND(!ginstance); +	ginstance->data->use_baked_light = p_enable; +	_geometry_instance_mark_dirty(ginstance); +} +void RendererSceneRenderForward::geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) { +	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +	ERR_FAIL_COND(!ginstance); +	ginstance->data->use_dynamic_gi = p_enable; +	_geometry_instance_mark_dirty(ginstance); +} +void RendererSceneRenderForward::geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) { +	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +	ERR_FAIL_COND(!ginstance); +	ginstance->lightmap_instance = p_lightmap_instance; +	ginstance->data->lightmap_uv_scale = p_lightmap_uv_scale; +	ginstance->data->lightmap_slice_index = p_lightmap_slice_index; +	_geometry_instance_mark_dirty(ginstance); +} +void RendererSceneRenderForward::geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) { +	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +	ERR_FAIL_COND(!ginstance); +	if (p_sh9) { +		if (ginstance->lightmap_sh == nullptr) { +			ginstance->lightmap_sh = geometry_instance_lightmap_sh.alloc(); +		} + +		copymem(ginstance->lightmap_sh->sh, p_sh9, sizeof(Color) * 9); +	} else { +		if (ginstance->lightmap_sh != nullptr) { +			geometry_instance_lightmap_sh.free(ginstance->lightmap_sh); +			ginstance->lightmap_sh = nullptr; +		} +	} +	_geometry_instance_mark_dirty(ginstance); +} +void RendererSceneRenderForward::geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) { +	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +	ERR_FAIL_COND(!ginstance); +	ginstance->data->shader_parameters_offset = p_offset; +	_geometry_instance_mark_dirty(ginstance); +} +void RendererSceneRenderForward::geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) { +	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +	ERR_FAIL_COND(!ginstance); + +	ginstance->data->cast_double_sided_shaodows = p_enable; +	_geometry_instance_mark_dirty(ginstance); +} + +void RendererSceneRenderForward::geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) { +	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +	ERR_FAIL_COND(!ginstance); +	ginstance->data->layer_mask = p_layer_mask; +	ginstance->push_constant.layer_mask = p_layer_mask; +} + +void RendererSceneRenderForward::geometry_instance_free(GeometryInstance *p_geometry_instance) { +	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +	ERR_FAIL_COND(!ginstance); +	if (ginstance->lightmap_sh != nullptr) { +		geometry_instance_lightmap_sh.free(ginstance->lightmap_sh); +	} +	GeometryInstanceSurfaceDataCache *surf = ginstance->surface_caches; +	while (surf) { +		GeometryInstanceSurfaceDataCache *next = surf->next; +		geometry_instance_surface_alloc.free(surf); +		surf = next; +	} +	memdelete(ginstance->data); +	geometry_instance_alloc.free(ginstance); +} + +uint32_t RendererSceneRenderForward::geometry_instance_get_pair_mask() { +	return (1 << RS::INSTANCE_GI_PROBE); +} +void RendererSceneRenderForward::geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) { +} +void RendererSceneRenderForward::geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) { +} +void RendererSceneRenderForward::geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) { +} + +Transform RendererSceneRenderForward::geometry_instance_get_transform(GeometryInstance *p_instance) { +	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_instance); +	ERR_FAIL_COND_V(!ginstance, Transform()); +	return ginstance->data->transform; +} +AABB RendererSceneRenderForward::geometry_instance_get_aabb(GeometryInstance *p_instance) { +	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_instance); +	ERR_FAIL_COND_V(!ginstance, AABB()); +	return ginstance->data->aabb; +} + +void RendererSceneRenderForward::geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count) { +	GeometryInstanceForward *ginstance = static_cast<GeometryInstanceForward *>(p_geometry_instance); +	ERR_FAIL_COND(!ginstance); +	if (p_gi_probe_instance_count > 0) { +		ginstance->gi_probes[0] = p_gi_probe_instances[0]; +	} else { +		ginstance->gi_probes[0] = RID(); +	} + +	if (p_gi_probe_instance_count > 1) { +		ginstance->gi_probes[1] = p_gi_probe_instances[1]; +	} else { +		ginstance->gi_probes[1] = RID(); +	} +} +  RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_storage) :  		RendererSceneRenderRD(p_storage) {  	singleton = this; @@ -2788,11 +3139,10 @@ RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_stor  		{  			//lightmaps -			scene_state.max_lightmaps = storage->lightmap_array_get_size(); +			scene_state.max_lightmaps = low_end ? 2 : MAX_LIGHTMAPS;  			defines += "\n#define MAX_LIGHTMAP_TEXTURES " + itos(scene_state.max_lightmaps) + "\n";  			defines += "\n#define MAX_LIGHTMAPS " + itos(scene_state.max_lightmaps) + "\n"; -			scene_state.lightmaps = memnew_arr(LightmapData, scene_state.max_lightmaps);  			scene_state.lightmap_buffer = RD::get_singleton()->storage_buffer_create(sizeof(LightmapData) * scene_state.max_lightmaps);  		}  		{ @@ -3015,12 +3365,6 @@ RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_stor  	render_list.init();  	render_pass = 0; -	{ -		scene_state.max_instances = render_list.max_elements; -		scene_state.instances = memnew_arr(InstanceData, scene_state.max_instances); -		scene_state.instance_buffer = RD::get_singleton()->storage_buffer_create(sizeof(InstanceData) * scene_state.max_instances); -	} -  	scene_state.uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SceneState::UBO));  	{ @@ -3068,6 +3412,8 @@ RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_stor  		sampler.compare_op = RD::COMPARE_OP_LESS;  		shadow_sampler = RD::get_singleton()->sampler_create(sampler);  	} + +	render_list_thread_threshold = GLOBAL_GET("rendering/forward_renderer/threaded_render_minimum_instances");  }  RendererSceneRenderForward::~RendererSceneRenderForward() { @@ -3095,11 +3441,8 @@ RendererSceneRenderForward::~RendererSceneRenderForward() {  	{  		RD::get_singleton()->free(scene_state.uniform_buffer); -		RD::get_singleton()->free(scene_state.instance_buffer);  		RD::get_singleton()->free(scene_state.lightmap_buffer);  		RD::get_singleton()->free(scene_state.lightmap_capture_buffer); -		memdelete_arr(scene_state.instances); -		memdelete_arr(scene_state.lightmaps);  		memdelete_arr(scene_state.lightmap_captures);  	} diff --git a/servers/rendering/renderer_rd/renderer_scene_render_forward.h b/servers/rendering/renderer_rd/renderer_scene_render_forward.h index 4b37f4a391..3b5a5ad96f 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_forward.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_forward.h @@ -31,6 +31,7 @@  #ifndef RENDERING_SERVER_SCENE_RENDER_FORWARD_H  #define RENDERING_SERVER_SCENE_RENDER_FORWARD_H +#include "core/templates/paged_allocator.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" @@ -46,7 +47,9 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {  	enum {  		SDFGI_MAX_CASCADES = 8, -		MAX_GI_PROBES = 8 +		MAX_GI_PROBES = 8, +		MAX_LIGHTMAPS = 8, +		MAX_GI_PROBES_PER_INSTANCE = 2,  	};  	/* Scene Shader */ @@ -166,6 +169,8 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {  		virtual bool is_animated() const;  		virtual bool casts_shadows() const;  		virtual Variant get_default_parameter(const StringName &p_parameter) const; +		virtual RS::ShaderNativeSourceCode get_native_source_code() const; +  		ShaderData();  		virtual ~ShaderData();  	}; @@ -197,14 +202,6 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {  		return static_cast<RendererSceneRenderForward *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));  	} -	/* Push Constant */ - -	struct PushConstant { -		uint32_t index; -		uint32_t pad; -		float bake_uv2_offset[2]; -	}; -  	/* Framebuffer */  	struct RenderBufferDataForward : public RenderBufferData { @@ -266,7 +263,7 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {  	void _update_render_base_uniform_set();  	RID _setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture); -	RID _setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, const PagedArray<RID> &p_gi_probes); +	RID _setup_render_pass_uniform_set(RID p_render_buffers, RID p_radiance_texture, RID p_shadow_atlas, RID p_reflection_atlas, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps);  	struct LightmapData {  		float normal_xform[12]; @@ -292,16 +289,6 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {  		INSTANCE_DATA_FLAG_SKELETON = 1 << 19,  	}; -	struct InstanceData { -		float transform[16]; -		float normal_transform[16]; -		uint32_t flags; -		uint32_t instance_uniforms_ofs; //instance_offset in instancing/skeleton buffer -		uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap) -		uint32_t mask; -		float lightmap_uv_scale[4]; -	}; -  	struct SceneState {  		struct UBO {  			float projection_matrix[16]; @@ -385,7 +372,10 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {  		RID uniform_buffer; -		LightmapData *lightmaps; +		LightmapData lightmaps[MAX_LIGHTMAPS]; +		RID lightmap_ids[MAX_LIGHTMAPS]; +		bool lightmap_has_sh[MAX_LIGHTMAPS]; +		uint32_t lightmaps_used = 0;  		uint32_t max_lightmaps;  		RID lightmap_buffer; @@ -393,47 +383,231 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {  		uint32_t max_lightmap_captures;  		RID lightmap_capture_buffer; -		RID instance_buffer; -		InstanceData *instances; -		uint32_t max_instances; +		RID giprobe_ids[MAX_GI_PROBES]; +		uint32_t giprobes_used = 0;  		bool used_screen_texture = false;  		bool used_normal_texture = false;  		bool used_depth_texture = false;  		bool used_sss = false; -		uint32_t current_shader_index = 0; -		uint32_t current_material_index = 0;  	} scene_state; -	/* Render List */ +	static RendererSceneRenderForward *singleton; +	uint64_t render_pass; +	double time; +	RID default_shader; +	RID default_material; +	RID overdraw_material_shader; +	RID overdraw_material; +	RID wireframe_material_shader; +	RID wireframe_material; +	RID default_shader_rd; +	RID default_shader_sdfgi_rd; -	struct RenderList { -		int max_elements; +	RID default_vec4_xform_buffer; +	RID default_vec4_xform_uniform_set; -		struct Element { -			RendererSceneRender::InstanceBase *instance; -			MaterialData *material; -			union { -				struct { -					//from least significant to most significant in sort, TODO: should be endian swapped on big endian -					uint64_t geometry_index : 20; -					uint64_t material_index : 15; -					uint64_t shader_index : 12; -					uint64_t uses_instancing : 1; -					uint64_t uses_forward_gi : 1; -					uint64_t uses_lightmap : 1; -					uint64_t depth_layer : 4; -					uint64_t priority : 8; -				}; - -				uint64_t sort_key; +	enum PassMode { +		PASS_MODE_COLOR, +		PASS_MODE_COLOR_SPECULAR, +		PASS_MODE_COLOR_TRANSPARENT, +		PASS_MODE_SHADOW, +		PASS_MODE_SHADOW_DP, +		PASS_MODE_DEPTH, +		PASS_MODE_DEPTH_NORMAL_ROUGHNESS, +		PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE, +		PASS_MODE_DEPTH_MATERIAL, +		PASS_MODE_SDF, +	}; + +	void _setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false); +	void _setup_giprobes(const PagedArray<RID> &p_giprobes); +	void _setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform &p_cam_transform); + +	struct GeometryInstanceSurfaceDataCache; + +	struct RenderListParameters { +		GeometryInstanceSurfaceDataCache **elements = nullptr; +		int element_count = 0; +		bool reverse_cull = false; +		PassMode pass_mode = PASS_MODE_COLOR; +		bool no_gi = false; +		RID render_pass_uniform_set; +		bool force_wireframe = false; +		Vector2 uv_offset; +		Plane lod_plane; +		float lod_distance_multiplier = 0.0; +		float screen_lod_threshold = 0.0; +		RD::FramebufferFormatID framebuffer_format = 0; +		RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0) { +			elements = p_elements; +			element_count = p_element_count; +			reverse_cull = p_reverse_cull; +			pass_mode = p_pass_mode; +			no_gi = p_no_gi; +			render_pass_uniform_set = p_render_pass_uniform_set; +			force_wireframe = p_force_wireframe; +			uv_offset = p_uv_offset; +			lod_plane = p_lod_plane; +			lod_distance_multiplier = p_lod_distance_multiplier; +			screen_lod_threshold = p_screen_lod_threshold; +		} +	}; + +	template <PassMode p_pass_mode> +	_FORCE_INLINE_ void _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); + +	void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element); + +	LocalVector<RD::DrawListID> thread_draw_lists; +	void _render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params); +	void _render_list_with_threads(RenderListParameters *p_params, RID p_framebuffer, RD::InitialAction p_initial_color_action, RD::FinalAction p_final_color_action, RD::InitialAction p_initial_depth_action, RD::FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()); + +	uint32_t render_list_thread_threshold = 500; + +	void _fill_render_list(const PagedArray<GeometryInstance *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi = false, bool p_using_opaque_gi = false); + +	Map<Size2i, RID> sdfgi_framebuffer_size_cache; + +	struct GeometryInstanceData; +	struct GeometryInstanceForward; + +	struct GeometryInstanceLightmapSH { +		Color sh[9]; +	}; + +	// Cached data for drawing surfaces +	struct GeometryInstanceSurfaceDataCache { +		enum { +			FLAG_PASS_DEPTH = 1, +			FLAG_PASS_OPAQUE = 2, +			FLAG_PASS_ALPHA = 4, +			FLAG_PASS_SHADOW = 8, +			FLAG_USES_SHARED_SHADOW_MATERIAL = 128, +			FLAG_USES_SUBSURFACE_SCATTERING = 2048, +			FLAG_USES_SCREEN_TEXTURE = 4096, +			FLAG_USES_DEPTH_TEXTURE = 8192, +			FLAG_USES_NORMAL_TEXTURE = 16384, +			FLAG_USES_DOUBLE_SIDED_SHADOWS = 32768, +		}; + +		union { +			struct { +				uint32_t geometry_id; +				uint32_t material_id; +				uint32_t shader_id; +				uint32_t surface_type : 4; +				uint32_t uses_forward_gi : 1; //set during addition +				uint32_t uses_lightmap : 1; //set during addition +				uint32_t depth_layer : 4; //set during addition +				uint32_t priority : 8; +			}; +			struct { +				uint64_t sort_key1; +				uint64_t sort_key2;  			}; -			uint32_t surface_index; +		} sort; + +		RS::PrimitiveType primitive = RS::PRIMITIVE_MAX; +		uint32_t flags = 0; +		uint32_t surface_index = 0; + +		void *surface = nullptr; +		RID material_uniform_set; +		ShaderData *shader = nullptr; + +		void *surface_shadow = nullptr; +		RID material_uniform_set_shadow; +		ShaderData *shader_shadow = nullptr; + +		GeometryInstanceSurfaceDataCache *next = nullptr; +		GeometryInstanceForward *owner = nullptr; +	}; + +	struct GeometryInstanceForward : public GeometryInstance { +		//used during rendering +		bool mirror = false; +		bool non_uniform_scale = false; +		float lod_bias = 0.0; +		float lod_model_scale = 1.0; +		AABB transformed_aabb; //needed for LOD +		float depth = 0; +		struct PushConstant { +			float 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) +			uint32_t layer_mask; +			float lightmap_uv_scale[4]; +		} push_constant; +		RID transforms_uniform_set; +		uint32_t instance_count = 0; +		RID mesh_instance; +		bool can_sdfgi = false; +		//used during setup +		uint32_t base_flags = 0; +		RID gi_probes[MAX_GI_PROBES_PER_INSTANCE]; +		RID lightmap_instance; +		GeometryInstanceLightmapSH *lightmap_sh = nullptr; +		GeometryInstanceSurfaceDataCache *surface_caches = nullptr; +		SelfList<GeometryInstanceForward> dirty_list_element; + +		struct Data { +			//data used less often goes into regular heap +			RID base; +			RS::InstanceType base_type; + +			RID skeleton; + +			uint32_t layer_mask = 1; + +			Vector<RID> surface_materials; +			RID material_override; +			Transform transform; +			AABB aabb; +			int32_t shader_parameters_offset = -1; + +			bool use_dynamic_gi = false; +			bool use_baked_light = false; +			bool cast_double_sided_shaodows = false; +			bool mirror = false; +			Rect2 lightmap_uv_scale; +			uint32_t lightmap_slice_index = 0; +			bool dirty_dependencies = false; + +			RendererStorage::DependencyTracker dependency_tracker;  		}; -		Element *base_elements; -		Element **elements; +		Data *data = nullptr; + +		GeometryInstanceForward() : +				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); + +	SelfList<GeometryInstanceForward>::List geometry_instance_dirty_list; + +	PagedAllocator<GeometryInstanceForward> geometry_instance_alloc; +	PagedAllocator<GeometryInstanceSurfaceDataCache> geometry_instance_surface_alloc; +	PagedAllocator<GeometryInstanceLightmapSH> geometry_instance_lightmap_sh; + +	void _geometry_instance_add_surface_with_material(GeometryInstanceForward *ginstance, uint32_t p_surface, MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh); +	void _geometry_instance_add_surface(GeometryInstanceForward *ginstance, uint32_t p_surface, RID p_material, RID p_mesh); +	void _geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance); +	void _geometry_instance_update(GeometryInstance *p_geometry_instance); +	void _update_dirty_geometry_instances(); + +	bool low_end = false; + +	/* Render List */ + +	struct RenderList { +		int max_elements; + +		GeometryInstanceSurfaceDataCache **elements = nullptr;  		int element_count;  		int alpha_element_count; @@ -446,13 +620,13 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {  		//should eventually be replaced by radix  		struct SortByKey { -			_FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const { -				return A->sort_key < B->sort_key; +			_FORCE_INLINE_ bool operator()(const GeometryInstanceSurfaceDataCache *A, const GeometryInstanceSurfaceDataCache *B) const { +				return (A->sort.sort_key2 == B->sort.sort_key2) ? (A->sort.sort_key1 < B->sort.sort_key1) : (A->sort.sort_key2 < B->sort.sort_key2);  			}  		};  		void sort_by_key(bool p_alpha) { -			SortArray<Element *, SortByKey> sorter; +			SortArray<GeometryInstanceSurfaceDataCache *, SortByKey> sorter;  			if (p_alpha) {  				sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);  			} else { @@ -461,14 +635,14 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {  		}  		struct SortByDepth { -			_FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const { -				return A->instance->depth < B->instance->depth; +			_FORCE_INLINE_ bool operator()(const GeometryInstanceSurfaceDataCache *A, const GeometryInstanceSurfaceDataCache *B) const { +				return (A->owner->depth < B->owner->depth);  			}  		};  		void sort_by_depth(bool p_alpha) { //used for shadows -			SortArray<Element *, SortByDepth> sorter; +			SortArray<GeometryInstanceSurfaceDataCache *, SortByDepth> sorter;  			if (p_alpha) {  				sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);  			} else { @@ -477,20 +651,14 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {  		}  		struct SortByReverseDepthAndPriority { -			_FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const { -				uint32_t layer_A = uint32_t(A->priority); -				uint32_t layer_B = uint32_t(B->priority); -				if (layer_A == layer_B) { -					return A->instance->depth > B->instance->depth; -				} else { -					return layer_A < layer_B; -				} +			_FORCE_INLINE_ bool operator()(const GeometryInstanceSurfaceDataCache *A, const GeometryInstanceSurfaceDataCache *B) const { +				return (A->sort.priority == B->sort.priority) ? (A->owner->depth > B->owner->depth) : (A->sort.priority < B->sort.priority);  			}  		};  		void sort_by_reverse_depth_and_priority(bool p_alpha) { //used for alpha -			SortArray<Element *, SortByReverseDepthAndPriority> sorter; +			SortArray<GeometryInstanceSurfaceDataCache *, SortByReverseDepthAndPriority> sorter;  			if (p_alpha) {  				sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count);  			} else { @@ -498,32 +666,27 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {  			}  		} -		_FORCE_INLINE_ Element *add_element() { +		_FORCE_INLINE_ void add_element(GeometryInstanceSurfaceDataCache *p_element) {  			if (element_count + alpha_element_count >= max_elements) { -				return nullptr; +				return;  			} -			elements[element_count] = &base_elements[element_count]; -			return elements[element_count++]; +			elements[element_count] = p_element; +			element_count++;  		} -		_FORCE_INLINE_ Element *add_alpha_element() { +		_FORCE_INLINE_ void add_alpha_element(GeometryInstanceSurfaceDataCache *p_element) {  			if (element_count + alpha_element_count >= max_elements) { -				return nullptr; +				return;  			}  			int idx = max_elements - alpha_element_count - 1; -			elements[idx] = &base_elements[idx]; +			elements[idx] = p_element;  			alpha_element_count++; -			return elements[idx];  		}  		void init() {  			element_count = 0;  			alpha_element_count = 0; -			elements = memnew_arr(Element *, max_elements); -			base_elements = memnew_arr(Element, max_elements); -			for (int i = 0; i < max_elements; i++) { -				elements[i] = &base_elements[i]; // assign elements -			} +			elements = memnew_arr(GeometryInstanceSurfaceDataCache *, max_elements);  		}  		RenderList() { @@ -532,63 +695,46 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {  		~RenderList() {  			memdelete_arr(elements); -			memdelete_arr(base_elements);  		}  	};  	RenderList render_list; -	static RendererSceneRenderForward *singleton; -	uint64_t render_pass; -	double time; -	RID default_shader; -	RID default_material; -	RID overdraw_material_shader; -	RID overdraw_material; -	RID wireframe_material_shader; -	RID wireframe_material; -	RID default_shader_rd; -	RID default_shader_sdfgi_rd; - -	RID default_vec4_xform_buffer; -	RID default_vec4_xform_uniform_set; - -	enum PassMode { -		PASS_MODE_COLOR, -		PASS_MODE_COLOR_SPECULAR, -		PASS_MODE_COLOR_TRANSPARENT, -		PASS_MODE_SHADOW, -		PASS_MODE_SHADOW_DP, -		PASS_MODE_DEPTH, -		PASS_MODE_DEPTH_NORMAL_ROUGHNESS, -		PASS_MODE_DEPTH_NORMAL_ROUGHNESS_GIPROBE, -		PASS_MODE_DEPTH_MATERIAL, -		PASS_MODE_SDF, -	}; - -	void _setup_environment(RID p_environment, RID p_render_buffers, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false); -	void _setup_lightmaps(const PagedArray<InstanceBase *> &p_lightmaps, const Transform &p_cam_transform); - -	void _fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth, bool p_has_sdfgi = false, bool p_has_opaque_gi = false); -	void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0); -	_FORCE_INLINE_ void _add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi = false); -	_FORCE_INLINE_ void _add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index, bool p_using_sdfgi = false); - -	void _fill_render_list(const PagedArray<InstanceBase *> &p_instances, PassMode p_pass_mode, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_using_sdfgi = false); - -	Map<Size2i, RID> sdfgi_framebuffer_size_cache; - -	bool low_end = false; -  protected: -	virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_lod_threshold); -	virtual void _render_shadow(RID p_framebuffer, const PagedArray<InstanceBase *> &p_instances, const CameraMatrix &p_projection, const Transform &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_lod_threshold = 0.0); -	virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region); -	virtual void _render_uv2(const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region); -	virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<InstanceBase *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture); -	virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<InstanceBase *> &p_instances); +	virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color, float p_lod_threshold); +	virtual void _render_shadow(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &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_lod_threshold = 0.0); +	virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region); +	virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region); +	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); +	virtual void _render_particle_collider_heightfield(RID p_fb, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances);  public: +	virtual GeometryInstance *geometry_instance_create(RID p_base); +	virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton); +	virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override); +	virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials); +	virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance); +	virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb); +	virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask); +	virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias); +	virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable); +	virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable); +	virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index); +	virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9); +	virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset); +	virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable); + +	virtual Transform geometry_instance_get_transform(GeometryInstance *p_instance); +	virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance); + +	virtual void geometry_instance_free(GeometryInstance *p_geometry_instance); + +	virtual uint32_t geometry_instance_get_pair_mask(); +	virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count); +	virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count); +	virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count); +	virtual void geometry_instance_pair_gi_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_gi_probe_instances, uint32_t p_gi_probe_instance_count); +  	virtual void set_time(double p_time, double p_step);  	virtual bool free(RID p_rid); diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 8e55dea2b1..188bcde8d7 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -2674,6 +2674,12 @@ Variant RendererSceneRenderRD::SkyShaderData::get_default_parameter(const String  	return Variant();  } +RS::ShaderNativeSourceCode RendererSceneRenderRD::SkyShaderData::get_native_source_code() const { +	RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton; + +	return scene_singleton->sky_shader.shader.version_get_native_source_code(version); +} +  RendererSceneRenderRD::SkyShaderData::SkyShaderData() {  	valid = false;  } @@ -4035,6 +4041,19 @@ void RendererSceneRenderRD::decal_instance_set_transform(RID p_decal, const Tran  ///////////////////////////////// +RID RendererSceneRenderRD::lightmap_instance_create(RID p_lightmap) { +	LightmapInstance li; +	li.lightmap = p_lightmap; +	return lightmap_instance_owner.make_rid(li); +} +void RendererSceneRenderRD::lightmap_instance_set_transform(RID p_lightmap, const Transform &p_transform) { +	LightmapInstance *li = lightmap_instance_owner.getornull(p_lightmap); +	ERR_FAIL_COND(!li); +	li->transform = p_transform; +} + +///////////////////////////////// +  RID RendererSceneRenderRD::gi_probe_instance_create(RID p_base) {  	GIProbeInstance gi_probe;  	gi_probe.probe = p_base; @@ -4061,7 +4080,7 @@ bool RendererSceneRenderRD::gi_probe_needs_update(RID p_probe) const {  	return gi_probe->last_probe_version != storage->gi_probe_get_version(gi_probe->probe);  } -void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<InstanceBase *> &p_dynamic_objects) { +void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<GeometryInstance *> &p_dynamic_objects) {  	GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);  	ERR_FAIL_COND(!gi_probe); @@ -4578,13 +4597,10 @@ void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_ins  		//this could probably be better parallelized in compute..  		for (int i = 0; i < (int)p_dynamic_objects.size(); i++) { -			InstanceBase *instance = p_dynamic_objects[i]; -			//not used, so clear -			instance->depth_layer = 0; -			instance->depth = 0; +			GeometryInstance *instance = p_dynamic_objects[i];  			//transform aabb to giprobe -			AABB aabb = (to_probe_xform * instance->transform).xform(instance->aabb); +			AABB aabb = (to_probe_xform * geometry_instance_get_transform(instance)).xform(geometry_instance_get_aabb(instance));  			//this needs to wrap to grid resolution to avoid jitter  			//also extend margin a bit just in case @@ -5329,9 +5345,9 @@ void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environmen  	settings.blur_passes = ssao_blur_passes;  	settings.fadeout_from = ssao_fadeout_from;  	settings.fadeout_to = ssao_fadeout_to; -	settings.screen_size = Size2i(rb->width, rb->height); +	settings.full_screen_size = Size2i(rb->width, rb->height);  	settings.half_screen_size = Size2i(buffer_width, buffer_height); -	settings.quarter_size = Size2i(half_width, half_height); +	settings.quarter_screen_size = Size2i(half_width, half_height);  	storage->get_effects()->generate_ssao(rb->depth_texture, p_normal_buffer, rb->ssao.depth, rb->ssao.depth_slices, rb->ssao.ao_deinterleaved, rb->ssao.ao_deinterleaved_slices, rb->ssao.ao_pong, rb->ssao.ao_pong_slices, rb->ssao.ao_final, rb->ssao.importance_map[0], rb->ssao.importance_map[1], p_projection, settings, uniform_sets_are_invalid);  } @@ -7101,7 +7117,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e  	RD::get_singleton()->compute_list_end();  } -void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) { +void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold) {  	Color clear_color;  	if (p_render_buffers.is_valid()) {  		RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); @@ -7177,7 +7193,7 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const Transform &  	}  } -void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<InstanceBase *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) { +void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_lod_threshold) {  	LightInstance *light_instance = light_instance_owner.getornull(p_light);  	ERR_FAIL_COND(!light_instance); @@ -7353,11 +7369,11 @@ void RendererSceneRenderRD::render_shadow(RID p_light, RID p_shadow_atlas, int p  	}  } -void RendererSceneRenderRD::render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) { +void RendererSceneRenderRD::render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {  	_render_material(p_cam_transform, p_cam_projection, p_cam_ortogonal, p_instances, p_framebuffer, p_region);  } -void RendererSceneRenderRD::render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<InstanceBase *> &p_instances) { +void RendererSceneRenderRD::render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<GeometryInstance *> &p_instances) {  	//print_line("rendering region " + itos(p_region));  	RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers);  	ERR_FAIL_COND(!rb); @@ -7694,7 +7710,7 @@ void RendererSceneRenderRD::render_sdfgi(RID p_render_buffers, int p_region, con  	}  } -void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<InstanceBase *> &p_instances) { +void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<GeometryInstance *> &p_instances) {  	ERR_FAIL_COND(!storage->particles_collision_is_heightfield(p_collider));  	Vector3 extents = storage->particles_collision_get_extents(p_collider) * p_transform.basis.get_scale();  	CameraMatrix cm; @@ -7844,6 +7860,8 @@ bool RendererSceneRenderRD::free(RID p_rid) {  		reflection_probe_instance_owner.free(p_rid);  	} else if (decal_instance_owner.owns(p_rid)) {  		decal_instance_owner.free(p_rid); +	} else if (lightmap_instance_owner.owns(p_rid)) { +		lightmap_instance_owner.free(p_rid);  	} else if (gi_probe_instance_owner.owns(p_rid)) {  		GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_rid);  		if (gi_probe->texture.is_valid()) { @@ -7979,23 +7997,28 @@ TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Vecto  	//RID sampled_light; -	InstanceBase ins; +	GeometryInstance *gi = geometry_instance_create(p_base); -	ins.base_type = RSG::storage->get_base_type(p_base); -	ins.base = p_base; -	ins.materials.resize(RSG::storage->mesh_get_surface_count(p_base)); -	for (int i = 0; i < ins.materials.size(); i++) { -		if (i < p_material_overrides.size()) { -			ins.materials.write[i] = p_material_overrides[i]; +	uint32_t sc = RSG::storage->mesh_get_surface_count(p_base); +	Vector<RID> materials; +	materials.resize(sc); + +	for (uint32_t i = 0; i < sc; i++) { +		if (i < (uint32_t)p_material_overrides.size()) { +			materials.write[i] = p_material_overrides[i];  		}  	} +	geometry_instance_set_surface_materials(gi, materials); +  	if (cull_argument.size() == 0) {  		cull_argument.push_back(nullptr);  	} -	cull_argument[0] = &ins; +	cull_argument[0] = gi;  	_render_uv2(cull_argument, fb, Rect2i(0, 0, p_image_size.width, p_image_size.height)); +	geometry_instance_free(gi); +  	TypedArray<Image> ret;  	{ diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index af35e1b3b4..3f9c117602 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -109,12 +109,12 @@ protected:  	void _setup_reflections(const PagedArray<RID> &p_reflections, const Transform &p_camera_inverse_transform, RID p_environment);  	void _setup_giprobes(RID p_render_buffers, const Transform &p_transform, const PagedArray<RID> &p_gi_probes, uint32_t &r_gi_probes_used); -	virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color, float p_screen_lod_threshold) = 0; -	virtual void _render_shadow(RID p_framebuffer, const PagedArray<InstanceBase *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0) = 0; -	virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; -	virtual void _render_uv2(const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; -	virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<InstanceBase *> &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 Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<InstanceBase *> &p_instances) = 0; +	virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, int p_directional_light_count, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color, float p_screen_lod_threshold) = 0; +	virtual void _render_shadow(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0) = 0; +	virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; +	virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0; +	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 Transform &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) = 0;  	virtual void _debug_giprobe(RID p_gi_probe, RenderingDevice::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);  	void _debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform); @@ -137,8 +137,8 @@ protected:  	void _process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_ambient_buffer, RID p_reflection_buffer, RID p_gi_probe_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform, const PagedArray<RID> &p_gi_probes);  	// needed for a single argument calls (material and uv2) -	PagedArrayPool<InstanceBase *> cull_argument_pool; -	PagedArray<InstanceBase *> cull_argument; //need this to exist +	PagedArrayPool<GeometryInstance *> cull_argument_pool; +	PagedArray<GeometryInstance *> cull_argument; //need this to exist  private:  	RS::ViewportDebugDraw debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED;  	double time_step = 0; @@ -233,6 +233,7 @@ private:  		virtual bool is_animated() const;  		virtual bool casts_shadows() const;  		virtual Variant get_default_parameter(const StringName &p_parameter) const; +		virtual RS::ShaderNativeSourceCode get_native_source_code() const;  		SkyShaderData();  		virtual ~SkyShaderData();  	}; @@ -374,6 +375,15 @@ private:  	mutable RID_Owner<DecalInstance> decal_instance_owner; +	/* LIGHTMAP INSTANCE */ + +	struct LightmapInstance { +		RID lightmap; +		Transform transform; +	}; + +	mutable RID_Owner<LightmapInstance> lightmap_instance_owner; +  	/* GIPROBE INSTANCE */  	struct GIProbeLight { @@ -1473,6 +1483,9 @@ private:  	bool low_end = false;  public: +	virtual Transform geometry_instance_get_transform(GeometryInstance *p_instance) = 0; +	virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance) = 0; +  	/* SHADOW ATLAS API */  	RID shadow_atlas_create(); @@ -1822,10 +1835,25 @@ public:  		return decal->transform;  	} +	virtual RID lightmap_instance_create(RID p_lightmap); +	virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform &p_transform); +	_FORCE_INLINE_ bool lightmap_instance_is_valid(RID p_lightmap_instance) { +		return lightmap_instance_owner.getornull(p_lightmap_instance) != nullptr; +	} + +	_FORCE_INLINE_ RID lightmap_instance_get_lightmap(RID p_lightmap_instance) { +		LightmapInstance *li = lightmap_instance_owner.getornull(p_lightmap_instance); +		return li->lightmap; +	} +	_FORCE_INLINE_ Transform lightmap_instance_get_transform(RID p_lightmap_instance) { +		LightmapInstance *li = lightmap_instance_owner.getornull(p_lightmap_instance); +		return li->transform; +	} +  	RID gi_probe_instance_create(RID p_base);  	void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform);  	bool gi_probe_needs_update(RID p_probe) const; -	void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::InstanceBase *> &p_dynamic_objects); +	void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects);  	void gi_probe_set_quality(RS::GIProbeQuality p_quality) { gi_probe_quality = p_quality; } @@ -1900,16 +1928,16 @@ public:  	float render_buffers_get_volumetric_fog_end(RID p_render_buffers);  	float render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers); -	void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<InstanceBase *> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold); +	void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_gi_probes, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_lod_threshold); -	void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<InstanceBase *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0); +	void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_lod_threshold = 0.0); -	void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<InstanceBase *> &p_instances, RID p_framebuffer, const Rect2i &p_region); +	void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region); -	void render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<InstanceBase *> &p_instances); +	void render_sdfgi(RID p_render_buffers, int p_region, const PagedArray<GeometryInstance *> &p_instances);  	void render_sdfgi_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); -	void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<InstanceBase *> &p_instances); +	void render_particle_collider_heightfield(RID p_collider, const Transform &p_transform, const PagedArray<GeometryInstance *> &p_instances);  	virtual void set_scene_pass(uint64_t p_pass) {  		scene_pass = p_pass; diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp index 68983da408..1ffc024d42 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -1438,7 +1438,7 @@ void RendererStorageRD::shader_set_code(RID p_shader, const String &p_code) {  	for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) {  		Material *material = E->get(); -		material->instance_dependency.instance_notify_changed(false, true); +		material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);  		_material_queue_update(material, true, true);  	}  } @@ -1499,6 +1499,15 @@ void RendererStorageRD::shader_set_data_request_function(ShaderType p_shader_typ  	shader_data_request_func[p_shader_type] = p_function;  } +RS::ShaderNativeSourceCode RendererStorageRD::shader_get_native_source_code(RID p_shader) const { +	Shader *shader = shader_owner.getornull(p_shader); +	ERR_FAIL_COND_V(!shader, RS::ShaderNativeSourceCode()); +	if (shader->data) { +		return shader->data->get_native_source_code(); +	} +	return RS::ShaderNativeSourceCode(); +} +  /* COMMON MATERIAL API */  RID RendererStorageRD::material_create() { @@ -1547,7 +1556,8 @@ void RendererStorageRD::material_set_shader(RID p_material, RID p_shader) {  	}  	if (p_shader.is_null()) { -		material->instance_dependency.instance_notify_changed(false, true); +		material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL); +		material->shader_id = 0;  		return;  	} @@ -1555,6 +1565,7 @@ void RendererStorageRD::material_set_shader(RID p_material, RID p_shader) {  	ERR_FAIL_COND(!shader);  	material->shader = shader;  	material->shader_type = shader->type; +	material->shader_id = p_shader.get_local_index();  	shader->owners.insert(material);  	if (shader->type == SHADER_TYPE_MAX) { @@ -1568,7 +1579,7 @@ void RendererStorageRD::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->instance_dependency.instance_notify_changed(false, true); +	material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);  	_material_queue_update(material, true, true);  } @@ -1613,7 +1624,7 @@ void RendererStorageRD::material_set_next_pass(RID p_material, RID p_next_materi  		material->data->set_next_pass(p_next_material);  	} -	material->instance_dependency.instance_notify_changed(false, true); +	material->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);  }  void RendererStorageRD::material_set_render_priority(RID p_material, int priority) { @@ -1663,10 +1674,10 @@ void RendererStorageRD::material_get_instance_shader_parameters(RID p_material,  	}  } -void RendererStorageRD::material_update_dependency(RID p_material, InstanceBaseDependency *p_instance) { +void RendererStorageRD::material_update_dependency(RID p_material, DependencyTracker *p_instance) {  	Material *material = material_owner.getornull(p_material);  	ERR_FAIL_COND(!material); -	p_instance->update_dependency(&material->instance_dependency); +	p_instance->update_dependency(&material->dependency);  	if (material->next_pass.is_valid()) {  		material_update_dependency(material->next_pass, p_instance);  	} @@ -2596,7 +2607,7 @@ void RendererStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_su  		_mesh_instance_add_surface(mi, mesh, mesh->surface_count - 1);  	} -	mesh->instance_dependency.instance_notify_changed(true, true); +	mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);  	mesh->material_cache.clear();  } @@ -2638,7 +2649,7 @@ void RendererStorageRD::mesh_surface_set_material(RID p_mesh, int p_surface, RID  	ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);  	mesh->surfaces[p_surface]->material = p_material; -	mesh->instance_dependency.instance_notify_changed(false, true); +	mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MATERIAL);  	mesh->material_cache.clear();  } @@ -2858,8 +2869,8 @@ void RendererStorageRD::mesh_clear(RID p_mesh) {  		MeshInstance *mi = E->get();  		_mesh_instance_clear(mi);  	} -	mesh->instance_dependency.instance_notify_changed(true, true);  	mesh->has_bone_weights = false; +	mesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);  }  bool RendererStorageRD::mesh_needs_instance(RID p_mesh, bool p_has_skeleton) { @@ -3298,6 +3309,8 @@ void RendererStorageRD::multimesh_allocate(RID p_multimesh, int p_instances, RS:  	if (multimesh->instances) {  		multimesh->buffer = RD::get_singleton()->storage_buffer_create(multimesh->instances * multimesh->stride_cache * 4);  	} + +	multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MULTIMESH);  }  int RendererStorageRD::multimesh_get_instance_count(RID p_multimesh) const { @@ -3331,7 +3344,7 @@ void RendererStorageRD::multimesh_set_mesh(RID p_multimesh, RID p_mesh) {  		}  	} -	multimesh->instance_dependency.instance_notify_changed(true, true); +	multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MESH);  }  #define MULTIMESH_DIRTY_REGION_SIZE 512 @@ -3690,7 +3703,7 @@ void RendererStorageRD::multimesh_set_buffer(RID p_multimesh, const Vector<float  		const float *data = p_buffer.ptr();  		_multimesh_re_create_aabb(multimesh, data, multimesh->instances); -		multimesh->instance_dependency.instance_notify_changed(true, false); +		multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);  	}  } @@ -3731,6 +3744,8 @@ void RendererStorageRD::multimesh_set_visible_instances(RID p_multimesh, int p_v  	}  	multimesh->visible_instances = p_visible; + +	multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES);  }  int RendererStorageRD::multimesh_get_visible_instances(RID p_multimesh) const { @@ -3788,7 +3803,7 @@ void RendererStorageRD::_update_dirty_multimeshes() {  				//aabb is dirty..  				_multimesh_re_create_aabb(multimesh, data, visible_instances);  				multimesh->aabb_dirty = false; -				multimesh->instance_dependency.instance_notify_changed(true, false); +				multimesh->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);  			}  		} @@ -3926,7 +3941,7 @@ void RendererStorageRD::particles_set_custom_aabb(RID p_particles, const AABB &p  	Particles *particles = particles_owner.getornull(p_particles);  	ERR_FAIL_COND(!particles);  	particles->custom_aabb = p_aabb; -	particles->instance_dependency.instance_notify_changed(true, false); +	particles->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);  }  void RendererStorageRD::particles_set_speed_scale(RID p_particles, float p_scale) { @@ -4155,24 +4170,18 @@ RID RendererStorageRD::particles_get_draw_pass_mesh(RID p_particles, int p_pass)  	return particles->draw_passes[p_pass];  } -void RendererStorageRD::particles_add_collision(RID p_particles, InstanceBaseDependency *p_instance) { -	RendererSceneRender::InstanceBase *instance = static_cast<RendererSceneRender::InstanceBase *>(p_instance); - +void RendererStorageRD::particles_add_collision(RID p_particles, RID p_particles_collision_instance) {  	Particles *particles = particles_owner.getornull(p_particles);  	ERR_FAIL_COND(!particles); -	ERR_FAIL_COND(instance->base_type != RS::INSTANCE_PARTICLES_COLLISION); - -	particles->collisions.insert(instance); +	particles->collisions.insert(p_particles_collision_instance);  } -void RendererStorageRD::particles_remove_collision(RID p_particles, InstanceBaseDependency *p_instance) { -	RendererSceneRender::InstanceBase *instance = static_cast<RendererSceneRender::InstanceBase *>(p_instance); - +void RendererStorageRD::particles_remove_collision(RID p_particles, RID p_particles_collision_instance) {  	Particles *particles = particles_owner.getornull(p_particles);  	ERR_FAIL_COND(!particles); -	particles->collisions.erase(instance); +	particles->collisions.erase(p_particles_collision_instance);  }  void RendererStorageRD::_particles_process(Particles *p_particles, float p_delta) { @@ -4272,9 +4281,15 @@ void RendererStorageRD::_particles_process(Particles *p_particles, float p_delta  			to_particles = p_particles->emission_transform.affine_inverse();  		}  		uint32_t collision_3d_textures_used = 0; -		for (const Set<RendererSceneRender::InstanceBase *>::Element *E = p_particles->collisions.front(); E; E = E->next()) { -			ParticlesCollision *pc = particles_collision_owner.getornull(E->get()->base); -			Transform to_collider = E->get()->transform; +		for (const Set<RID>::Element *E = p_particles->collisions.front(); E; E = E->next()) { +			ParticlesCollisionInstance *pci = particles_collision_instance_owner.getornull(E->get()); +			if (!pci || !pci->active) { +				continue; +			} +			ParticlesCollision *pc = particles_collision_owner.getornull(pci->collision); +			ERR_CONTINUE(!pc); + +			Transform to_collider = pci->transform;  			if (p_particles->use_local_coords) {  				to_collider = to_particles * to_collider;  			} @@ -4687,7 +4702,7 @@ void RendererStorageRD::update_particles() {  			RD::get_singleton()->compute_list_end();  		} -		particles->instance_dependency.instance_notify_changed(true, false); //make sure shadows are updated +		particles->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);  	}  } @@ -4817,6 +4832,10 @@ Variant RendererStorageRD::ParticlesShaderData::get_default_parameter(const Stri  	return Variant();  } +RS::ShaderNativeSourceCode RendererStorageRD::ParticlesShaderData::get_native_source_code() const { +	return base_singleton->particles_shader.shader.version_get_native_source_code(version); +} +  RendererStorageRD::ParticlesShaderData::ParticlesShaderData() {  	valid = false;  } @@ -4986,7 +5005,7 @@ void RendererStorageRD::particles_collision_set_collision_type(RID p_particles_c  		particles_collision->heightfield_texture = RID();  	}  	particles_collision->type = p_type; -	particles_collision->instance_dependency.instance_notify_changed(true, false); +	particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);  }  void RendererStorageRD::particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) { @@ -5000,7 +5019,7 @@ void RendererStorageRD::particles_collision_set_sphere_radius(RID p_particles_co  	ERR_FAIL_COND(!particles_collision);  	particles_collision->radius = p_radius; -	particles_collision->instance_dependency.instance_notify_changed(true, false); +	particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);  }  void RendererStorageRD::particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) { @@ -5008,7 +5027,7 @@ void RendererStorageRD::particles_collision_set_box_extents(RID p_particles_coll  	ERR_FAIL_COND(!particles_collision);  	particles_collision->extents = p_extents; -	particles_collision->instance_dependency.instance_notify_changed(true, false); +	particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);  }  void RendererStorageRD::particles_collision_set_attractor_strength(RID p_particles_collision, float p_strength) { @@ -5042,7 +5061,7 @@ void RendererStorageRD::particles_collision_set_field_texture(RID p_particles_co  void RendererStorageRD::particles_collision_height_field_update(RID p_particles_collision) {  	ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_particles_collision);  	ERR_FAIL_COND(!particles_collision); -	particles_collision->instance_dependency.instance_notify_changed(true, false); +	particles_collision->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);  }  void RendererStorageRD::particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) { @@ -5096,6 +5115,22 @@ bool RendererStorageRD::particles_collision_is_heightfield(RID p_particles_colli  	return particles_collision->type == RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE;  } +RID RendererStorageRD::particles_collision_instance_create(RID p_collision) { +	ParticlesCollisionInstance pci; +	pci.collision = p_collision; +	return particles_collision_instance_owner.make_rid(pci); +} +void RendererStorageRD::particles_collision_instance_set_transform(RID p_collision_instance, const Transform &p_transform) { +	ParticlesCollisionInstance *pci = particles_collision_instance_owner.getornull(p_collision_instance); +	ERR_FAIL_COND(!pci); +	pci->transform = p_transform; +} +void RendererStorageRD::particles_collision_instance_set_active(RID p_collision_instance, bool p_active) { +	ParticlesCollisionInstance *pci = particles_collision_instance_owner.getornull(p_collision_instance); +	ERR_FAIL_COND(!pci); +	pci->active = p_active; +} +  /* SKELETON API */  RID RendererStorageRD::skeleton_create() { @@ -5149,6 +5184,8 @@ void RendererStorageRD::skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d  			skeleton->uniform_set_mi = RD::get_singleton()->uniform_set_create(uniforms, skeleton_shader.version_shader[0], SkeletonShader::UNIFORM_SET_SKELETON);  		}  	} + +	skeleton->dependency.changed_notify(DEPENDENCY_CHANGED_SKELETON_DATA);  }  int RendererStorageRD::skeleton_get_bone_count(RID p_skeleton) const { @@ -5269,7 +5306,8 @@ void RendererStorageRD::_update_dirty_skeletons() {  		skeleton_dirty_list = skeleton->dirty_list; -		skeleton->instance_dependency.instance_notify_changed(true, false); +		skeleton->dependency.changed_notify(DEPENDENCY_CHANGED_SKELETON_BONES); +  		skeleton->version++;  		skeleton->dirty = false; @@ -5290,17 +5328,20 @@ RID RendererStorageRD::light_create(RS::LightType p_type) {  	light.param[RS::LIGHT_PARAM_SPECULAR] = 0.5;  	light.param[RS::LIGHT_PARAM_RANGE] = 1.0;  	light.param[RS::LIGHT_PARAM_SIZE] = 0.0; +	light.param[RS::LIGHT_PARAM_ATTENUATION] = 1.0;  	light.param[RS::LIGHT_PARAM_SPOT_ANGLE] = 45; +	light.param[RS::LIGHT_PARAM_SPOT_ATTENUATION] = 1.0;  	light.param[RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE] = 0;  	light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1;  	light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3;  	light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6;  	light.param[RS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8; -	light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02;  	light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 1.0; +	light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02; +	light.param[RS::LIGHT_PARAM_SHADOW_BLUR] = 0;  	light.param[RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE] = 20.0; -	light.param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] = 0.05;  	light.param[RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE] = 1.0; +	light.param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] = 0.05;  	return light_owner.make_rid(light);  } @@ -5328,7 +5369,7 @@ void RendererStorageRD::light_set_param(RID p_light, RS::LightParam p_param, flo  		case RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE:  		case RS::LIGHT_PARAM_SHADOW_BIAS: {  			light->version++; -			light->instance_dependency.instance_notify_changed(true, false); +			light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);  		} break;  		default: {  		} @@ -5343,7 +5384,7 @@ void RendererStorageRD::light_set_shadow(RID p_light, bool p_enabled) {  	light->shadow = p_enabled;  	light->version++; -	light->instance_dependency.instance_notify_changed(true, false); +	light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);  }  void RendererStorageRD::light_set_shadow_color(RID p_light, const Color &p_color) { @@ -5385,7 +5426,7 @@ void RendererStorageRD::light_set_cull_mask(RID p_light, uint32_t p_mask) {  	light->cull_mask = p_mask;  	light->version++; -	light->instance_dependency.instance_notify_changed(true, false); +	light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);  }  void RendererStorageRD::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) { @@ -5395,7 +5436,7 @@ void RendererStorageRD::light_set_reverse_cull_face_mode(RID p_light, bool p_ena  	light->reverse_cull = p_enabled;  	light->version++; -	light->instance_dependency.instance_notify_changed(true, false); +	light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);  }  void RendererStorageRD::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) { @@ -5405,7 +5446,7 @@ void RendererStorageRD::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bak  	light->bake_mode = p_bake_mode;  	light->version++; -	light->instance_dependency.instance_notify_changed(true, false); +	light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);  }  void RendererStorageRD::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) { @@ -5415,7 +5456,7 @@ void RendererStorageRD::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_casc  	light->max_sdfgi_cascade = p_cascade;  	light->version++; -	light->instance_dependency.instance_notify_changed(true, false); +	light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);  }  void RendererStorageRD::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) { @@ -5425,7 +5466,7 @@ void RendererStorageRD::light_omni_set_shadow_mode(RID p_light, RS::LightOmniSha  	light->omni_shadow_mode = p_mode;  	light->version++; -	light->instance_dependency.instance_notify_changed(true, false); +	light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);  }  RS::LightOmniShadowMode RendererStorageRD::light_omni_get_shadow_mode(RID p_light) { @@ -5441,7 +5482,7 @@ void RendererStorageRD::light_directional_set_shadow_mode(RID p_light, RS::Light  	light->directional_shadow_mode = p_mode;  	light->version++; -	light->instance_dependency.instance_notify_changed(true, false); +	light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);  }  void RendererStorageRD::light_directional_set_blend_splits(RID p_light, bool p_enable) { @@ -5450,7 +5491,7 @@ void RendererStorageRD::light_directional_set_blend_splits(RID p_light, bool p_e  	light->directional_blend_splits = p_enable;  	light->version++; -	light->instance_dependency.instance_notify_changed(true, false); +	light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);  }  bool RendererStorageRD::light_directional_get_blend_splits(RID p_light) const { @@ -5549,7 +5590,7 @@ void RendererStorageRD::reflection_probe_set_update_mode(RID p_probe, RS::Reflec  	ERR_FAIL_COND(!reflection_probe);  	reflection_probe->update_mode = p_mode; -	reflection_probe->instance_dependency.instance_notify_changed(true, false); +	reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);  }  void RendererStorageRD::reflection_probe_set_intensity(RID p_probe, float p_intensity) { @@ -5586,7 +5627,7 @@ void RendererStorageRD::reflection_probe_set_max_distance(RID p_probe, float p_d  	reflection_probe->max_distance = p_distance; -	reflection_probe->instance_dependency.instance_notify_changed(true, false); +	reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);  }  void RendererStorageRD::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) { @@ -5597,7 +5638,7 @@ void RendererStorageRD::reflection_probe_set_extents(RID p_probe, const Vector3  		return;  	}  	reflection_probe->extents = p_extents; -	reflection_probe->instance_dependency.instance_notify_changed(true, false); +	reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);  }  void RendererStorageRD::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) { @@ -5605,7 +5646,7 @@ void RendererStorageRD::reflection_probe_set_origin_offset(RID p_probe, const Ve  	ERR_FAIL_COND(!reflection_probe);  	reflection_probe->origin_offset = p_offset; -	reflection_probe->instance_dependency.instance_notify_changed(true, false); +	reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);  }  void RendererStorageRD::reflection_probe_set_as_interior(RID p_probe, bool p_enable) { @@ -5613,7 +5654,7 @@ void RendererStorageRD::reflection_probe_set_as_interior(RID p_probe, bool p_ena  	ERR_FAIL_COND(!reflection_probe);  	reflection_probe->interior = p_enable; -	reflection_probe->instance_dependency.instance_notify_changed(true, false); +	reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);  }  void RendererStorageRD::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) { @@ -5628,7 +5669,7 @@ void RendererStorageRD::reflection_probe_set_enable_shadows(RID p_probe, bool p_  	ERR_FAIL_COND(!reflection_probe);  	reflection_probe->enable_shadows = p_enable; -	reflection_probe->instance_dependency.instance_notify_changed(true, false); +	reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);  }  void RendererStorageRD::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) { @@ -5636,7 +5677,7 @@ void RendererStorageRD::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_l  	ERR_FAIL_COND(!reflection_probe);  	reflection_probe->cull_mask = p_layers; -	reflection_probe->instance_dependency.instance_notify_changed(true, false); +	reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);  }  void RendererStorageRD::reflection_probe_set_resolution(RID p_probe, int p_resolution) { @@ -5653,7 +5694,7 @@ void RendererStorageRD::reflection_probe_set_lod_threshold(RID p_probe, float p_  	reflection_probe->lod_threshold = p_ratio; -	reflection_probe->instance_dependency.instance_notify_changed(true, false); +	reflection_probe->dependency.changed_notify(DEPENDENCY_CHANGED_REFLECTION_PROBE);  }  AABB RendererStorageRD::reflection_probe_get_aabb(RID p_probe) const { @@ -5771,7 +5812,7 @@ void RendererStorageRD::decal_set_extents(RID p_decal, const Vector3 &p_extents)  	Decal *decal = decal_owner.getornull(p_decal);  	ERR_FAIL_COND(!decal);  	decal->extents = p_extents; -	decal->instance_dependency.instance_notify_changed(true, false); +	decal->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);  }  void RendererStorageRD::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) { @@ -5795,7 +5836,7 @@ void RendererStorageRD::decal_set_texture(RID p_decal, RS::DecalTexture p_type,  		texture_add_to_decal_atlas(decal->textures[p_type]);  	} -	decal->instance_dependency.instance_notify_changed(false, true); +	decal->dependency.changed_notify(DEPENDENCY_CHANGED_DECAL);  }  void RendererStorageRD::decal_set_emission_energy(RID p_decal, float p_energy) { @@ -5820,7 +5861,7 @@ void RendererStorageRD::decal_set_cull_mask(RID p_decal, uint32_t p_layers) {  	Decal *decal = decal_owner.getornull(p_decal);  	ERR_FAIL_COND(!decal);  	decal->cull_mask = p_layers; -	decal->instance_dependency.instance_notify_changed(true, false); +	decal->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);  }  void RendererStorageRD::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) { @@ -5977,7 +6018,7 @@ void RendererStorageRD::gi_probe_allocate(RID p_gi_probe, const Transform &p_to_  	gi_probe->version++;  	gi_probe->data_version++; -	gi_probe->instance_dependency.instance_notify_changed(true, false); +	gi_probe->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);  }  AABB RendererStorageRD::gi_probe_get_bounds(RID p_gi_probe) const { @@ -7055,45 +7096,45 @@ void RendererStorageRD::render_target_set_backbuffer_uniform_set(RID p_render_ta  	rt->backbuffer_uniform_set = p_uniform_set;  } -void RendererStorageRD::base_update_dependency(RID p_base, InstanceBaseDependency *p_instance) { +void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_instance) {  	if (mesh_owner.owns(p_base)) {  		Mesh *mesh = mesh_owner.getornull(p_base); -		p_instance->update_dependency(&mesh->instance_dependency); +		p_instance->update_dependency(&mesh->dependency);  	} else if (multimesh_owner.owns(p_base)) {  		MultiMesh *multimesh = multimesh_owner.getornull(p_base); -		p_instance->update_dependency(&multimesh->instance_dependency); +		p_instance->update_dependency(&multimesh->dependency);  		if (multimesh->mesh.is_valid()) {  			base_update_dependency(multimesh->mesh, p_instance);  		}  	} else if (reflection_probe_owner.owns(p_base)) {  		ReflectionProbe *rp = reflection_probe_owner.getornull(p_base); -		p_instance->update_dependency(&rp->instance_dependency); +		p_instance->update_dependency(&rp->dependency);  	} else if (decal_owner.owns(p_base)) {  		Decal *decal = decal_owner.getornull(p_base); -		p_instance->update_dependency(&decal->instance_dependency); +		p_instance->update_dependency(&decal->dependency);  	} else if (gi_probe_owner.owns(p_base)) {  		GIProbe *gip = gi_probe_owner.getornull(p_base); -		p_instance->update_dependency(&gip->instance_dependency); +		p_instance->update_dependency(&gip->dependency);  	} else if (lightmap_owner.owns(p_base)) {  		Lightmap *lm = lightmap_owner.getornull(p_base); -		p_instance->update_dependency(&lm->instance_dependency); +		p_instance->update_dependency(&lm->dependency);  	} else if (light_owner.owns(p_base)) {  		Light *l = light_owner.getornull(p_base); -		p_instance->update_dependency(&l->instance_dependency); +		p_instance->update_dependency(&l->dependency);  	} else if (particles_owner.owns(p_base)) {  		Particles *p = particles_owner.getornull(p_base); -		p_instance->update_dependency(&p->instance_dependency); +		p_instance->update_dependency(&p->dependency);  	} else if (particles_collision_owner.owns(p_base)) {  		ParticlesCollision *pc = particles_collision_owner.getornull(p_base); -		p_instance->update_dependency(&pc->instance_dependency); +		p_instance->update_dependency(&pc->dependency);  	}  } -void RendererStorageRD::skeleton_update_dependency(RID p_skeleton, InstanceBaseDependency *p_instance) { +void RendererStorageRD::skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance) {  	Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);  	ERR_FAIL_COND(!skeleton); -	p_instance->update_dependency(&skeleton->instance_dependency); +	p_instance->update_dependency(&skeleton->dependency);  }  RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const { @@ -8114,12 +8155,13 @@ bool RendererStorageRD::free(RID p_rid) {  			_update_queued_materials();  		}  		material_set_shader(p_rid, RID()); //clean up shader -		material->instance_dependency.instance_notify_deleted(p_rid); +		material->dependency.deleted_notify(p_rid); +  		material_owner.free(p_rid);  	} else if (mesh_owner.owns(p_rid)) {  		mesh_clear(p_rid);  		Mesh *mesh = mesh_owner.getornull(p_rid); -		mesh->instance_dependency.instance_notify_deleted(p_rid); +		mesh->dependency.deleted_notify(p_rid);  		if (mesh->instances.size()) {  			ERR_PRINT("deleting mesh with active instances");  		} @@ -8136,17 +8178,17 @@ bool RendererStorageRD::free(RID p_rid) {  		_update_dirty_multimeshes();  		multimesh_allocate(p_rid, 0, RS::MULTIMESH_TRANSFORM_2D);  		MultiMesh *multimesh = multimesh_owner.getornull(p_rid); -		multimesh->instance_dependency.instance_notify_deleted(p_rid); +		multimesh->dependency.deleted_notify(p_rid);  		multimesh_owner.free(p_rid);  	} else if (skeleton_owner.owns(p_rid)) {  		_update_dirty_skeletons();  		skeleton_allocate(p_rid, 0);  		Skeleton *skeleton = skeleton_owner.getornull(p_rid); -		skeleton->instance_dependency.instance_notify_deleted(p_rid); +		skeleton->dependency.deleted_notify(p_rid);  		skeleton_owner.free(p_rid);  	} else if (reflection_probe_owner.owns(p_rid)) {  		ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_rid); -		reflection_probe->instance_dependency.instance_notify_deleted(p_rid); +		reflection_probe->dependency.deleted_notify(p_rid);  		reflection_probe_owner.free(p_rid);  	} else if (decal_owner.owns(p_rid)) {  		Decal *decal = decal_owner.getornull(p_rid); @@ -8155,30 +8197,30 @@ bool RendererStorageRD::free(RID p_rid) {  				texture_remove_from_decal_atlas(decal->textures[i]);  			}  		} -		decal->instance_dependency.instance_notify_deleted(p_rid); +		decal->dependency.deleted_notify(p_rid);  		decal_owner.free(p_rid);  	} else if (gi_probe_owner.owns(p_rid)) {  		gi_probe_allocate(p_rid, Transform(), AABB(), Vector3i(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<int>()); //deallocate  		GIProbe *gi_probe = gi_probe_owner.getornull(p_rid); -		gi_probe->instance_dependency.instance_notify_deleted(p_rid); +		gi_probe->dependency.deleted_notify(p_rid);  		gi_probe_owner.free(p_rid);  	} else if (lightmap_owner.owns(p_rid)) {  		lightmap_set_textures(p_rid, RID(), false);  		Lightmap *lightmap = lightmap_owner.getornull(p_rid); -		lightmap->instance_dependency.instance_notify_deleted(p_rid); +		lightmap->dependency.deleted_notify(p_rid);  		lightmap_owner.free(p_rid);  	} else if (light_owner.owns(p_rid)) {  		light_set_projector(p_rid, RID()); //clear projector  		// delete the texture  		Light *light = light_owner.getornull(p_rid); -		light->instance_dependency.instance_notify_deleted(p_rid); +		light->dependency.deleted_notify(p_rid);  		light_owner.free(p_rid);  	} else if (particles_owner.owns(p_rid)) {  		Particles *particles = particles_owner.getornull(p_rid);  		_particles_free_data(particles); -		particles->instance_dependency.instance_notify_deleted(p_rid); +		particles->dependency.deleted_notify(p_rid);  		particles_owner.free(p_rid);  	} else if (particles_collision_owner.owns(p_rid)) {  		ParticlesCollision *particles_collision = particles_collision_owner.getornull(p_rid); @@ -8186,8 +8228,10 @@ bool RendererStorageRD::free(RID p_rid) {  		if (particles_collision->heightfield_texture.is_valid()) {  			RD::get_singleton()->free(particles_collision->heightfield_texture);  		} -		particles_collision->instance_dependency.instance_notify_deleted(p_rid); +		particles_collision->dependency.deleted_notify(p_rid);  		particles_collision_owner.free(p_rid); +	} else if (particles_collision_instance_owner.owns(p_rid)) { +		particles_collision_instance_owner.free(p_rid);  	} else if (render_target_owner.owns(p_rid)) {  		RenderTarget *rt = render_target_owner.getornull(p_rid); diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h index 6d1587185e..5ef73f0db8 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.h +++ b/servers/rendering/renderer_rd/renderer_storage_rd.h @@ -127,6 +127,8 @@ public:  		virtual bool is_animated() const = 0;  		virtual bool casts_shadows() const = 0;  		virtual Variant get_default_parameter(const StringName &p_parameter) const = 0; +		virtual RS::ShaderNativeSourceCode get_native_source_code() const { return RS::ShaderNativeSourceCode(); } +  		virtual ~ShaderData() {}  	}; @@ -360,6 +362,7 @@ private:  		Shader *shader;  		//shortcut to shader data and type  		ShaderType shader_type; +		uint32_t shader_id = 0;  		bool update_requested;  		bool uniform_dirty;  		bool texture_dirty; @@ -367,7 +370,7 @@ private:  		Map<StringName, Variant> params;  		int32_t priority;  		RID next_pass; -		RendererStorage::InstanceDependency instance_dependency; +		Dependency dependency;  	};  	MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX]; @@ -460,7 +463,7 @@ private:  		List<MeshInstance *> instances; -		RendererStorage::InstanceDependency instance_dependency; +		Dependency dependency;  	};  	mutable RID_Owner<Mesh> mesh_owner; @@ -563,7 +566,7 @@ private:  		bool dirty = false;  		MultiMesh *dirty_list = nullptr; -		RendererStorage::InstanceDependency instance_dependency; +		Dependency dependency;  	};  	mutable RID_Owner<MultiMesh> multimesh_owner; @@ -734,7 +737,7 @@ private:  		ParticleEmissionBuffer *emission_buffer = nullptr;  		RID emission_storage_buffer; -		Set<RendererSceneRender::InstanceBase *> collisions; +		Set<RID> collisions;  		Particles() :  				inactive(true), @@ -761,7 +764,7 @@ private:  				clear(true) {  		} -		RendererStorage::InstanceDependency instance_dependency; +		Dependency dependency;  		ParticlesFrameParams frame_params;  	}; @@ -839,6 +842,8 @@ private:  		virtual bool is_animated() const;  		virtual bool casts_shadows() const;  		virtual Variant get_default_parameter(const StringName &p_parameter) const; +		virtual RS::ShaderNativeSourceCode get_native_source_code() const; +  		ParticlesShaderData();  		virtual ~ParticlesShaderData();  	}; @@ -889,11 +894,19 @@ private:  		RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024; -		RendererStorage::InstanceDependency instance_dependency; +		Dependency dependency;  	};  	mutable RID_Owner<ParticlesCollision> particles_collision_owner; +	struct ParticlesCollisionInstance { +		RID collision; +		Transform transform; +		bool active = false; +	}; + +	mutable RID_Owner<ParticlesCollisionInstance> particles_collision_instance_owner; +  	/* Skeleton */  	struct Skeleton { @@ -911,7 +924,7 @@ private:  		uint64_t version = 1; -		RendererStorage::InstanceDependency instance_dependency; +		Dependency dependency;  	};  	mutable RID_Owner<Skeleton> skeleton_owner; @@ -943,7 +956,7 @@ private:  		bool directional_sky_only = false;  		uint64_t version = 0; -		RendererStorage::InstanceDependency instance_dependency; +		Dependency dependency;  	};  	mutable RID_Owner<Light> light_owner; @@ -966,7 +979,7 @@ private:  		uint32_t cull_mask = (1 << 20) - 1;  		float lod_threshold = 0.01; -		RendererStorage::InstanceDependency instance_dependency; +		Dependency dependency;  	};  	mutable RID_Owner<ReflectionProbe> reflection_probe_owner; @@ -987,7 +1000,7 @@ private:  		float distance_fade_length = 1;  		float normal_fade = 0.0; -		RendererStorage::InstanceDependency instance_dependency; +		Dependency dependency;  	};  	mutable RID_Owner<Decal> decal_owner; @@ -1025,7 +1038,7 @@ private:  		uint32_t version = 1;  		uint32_t data_version = 1; -		RendererStorage::InstanceDependency instance_dependency; +		Dependency dependency;  	};  	GiprobeSdfShaderRD giprobe_sdf_shader; @@ -1054,7 +1067,7 @@ private:  			int32_t over = EMPTY_LEAF, under = EMPTY_LEAF;  		}; -		RendererStorage::InstanceDependency instance_dependency; +		Dependency dependency;  	};  	bool using_lightmap_array; //high end uses this @@ -1330,6 +1343,8 @@ public:  	Variant shader_get_param_default(RID p_shader, const StringName &p_param) const;  	void shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function); +	virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const; +  	/* COMMON MATERIAL API */  	RID material_create(); @@ -1347,11 +1362,16 @@ public:  	void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters); -	void material_update_dependency(RID p_material, InstanceBaseDependency *p_instance); +	void material_update_dependency(RID p_material, DependencyTracker *p_instance);  	void material_force_update_textures(RID p_material, ShaderType p_shader_type);  	void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function); +	_FORCE_INLINE_ uint32_t material_get_shader_id(RID p_material) { +		Material *material = material_owner.getornull(p_material); +		return material->shader_id; +	} +  	_FORCE_INLINE_ MaterialData *material_get_data(RID p_material, ShaderType p_shader_type) {  		Material *material = material_owner.getornull(p_material);  		if (!material || material->shader_type != p_shader_type) { @@ -1664,6 +1684,10 @@ public:  	void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform);  	Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const; +	_FORCE_INLINE_ bool skeleton_is_valid(RID p_skeleton) { +		return skeleton_owner.getornull(p_skeleton) != nullptr; +	} +  	_FORCE_INLINE_ RID skeleton_get_3d_uniform_set(RID p_skeleton, RID p_shader, uint32_t p_set) const {  		Skeleton *skeleton = skeleton_owner.getornull(p_skeleton);  		ERR_FAIL_COND_V(!skeleton, RID()); @@ -1827,8 +1851,8 @@ public:  	Color reflection_probe_get_ambient_color(RID p_probe) const;  	float reflection_probe_get_ambient_color_energy(RID p_probe) const; -	void base_update_dependency(RID p_base, InstanceBaseDependency *p_instance); -	void skeleton_update_dependency(RID p_skeleton, InstanceBaseDependency *p_instance); +	void base_update_dependency(RID p_base, DependencyTracker *p_instance); +	void skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance);  	/* DECAL API */ @@ -1977,7 +2001,11 @@ public:  	_FORCE_INLINE_ float lightmap_get_probe_capture_update_speed() const {  		return lightmap_probe_capture_update_speed;  	} - +	_FORCE_INLINE_ RID lightmap_get_texture(RID p_lightmap) const { +		const Lightmap *lm = lightmap_owner.getornull(p_lightmap); +		ERR_FAIL_COND_V(!lm, RID()); +		return lm->light_texture; +	}  	_FORCE_INLINE_ int32_t lightmap_get_array_index(RID p_lightmap) const {  		ERR_FAIL_COND_V(!using_lightmap_array, -1); //only for arrays  		const Lightmap *lm = lightmap_owner.getornull(p_lightmap); @@ -2078,8 +2106,8 @@ public:  		return particles->particles_transforms_buffer_uniform_set;  	} -	virtual void particles_add_collision(RID p_particles, InstanceBaseDependency *p_instance); -	virtual void particles_remove_collision(RID p_particles, InstanceBaseDependency *p_instance); +	virtual void particles_add_collision(RID p_particles, RID p_particles_collision_instance); +	virtual void particles_remove_collision(RID p_particles, RID p_particles_collision_instance);  	/* PARTICLES COLLISION */ @@ -2099,6 +2127,11 @@ public:  	virtual bool particles_collision_is_heightfield(RID p_particles_collision) const;  	RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const; +	//used from 2D and 3D +	virtual RID particles_collision_instance_create(RID p_collision); +	virtual void particles_collision_instance_set_transform(RID p_collision_instance, const Transform &p_transform); +	virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active); +  	/* GLOBAL VARIABLES API */  	virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value); diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp index d1f07a354f..2ae22a8a38 100644 --- a/servers/rendering/renderer_rd/shader_rd.cpp +++ b/servers/rendering/renderer_rd/shader_rd.cpp @@ -351,6 +351,127 @@ void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) {  	}  } +RS::ShaderNativeSourceCode ShaderRD::version_get_native_source_code(RID p_version) { +	Version *version = version_owner.getornull(p_version); +	RS::ShaderNativeSourceCode source_code; +	ERR_FAIL_COND_V(!version, source_code); + +	source_code.versions.resize(variant_defines.size()); + +	for (int i = 0; i < source_code.versions.size(); i++) { +		if (!is_compute) { +			//vertex stage + +			StringBuilder builder; + +			builder.append(vertex_codev.get_data()); // version info (if exists) +			builder.append("\n"); //make sure defines begin at newline +			builder.append(general_defines.get_data()); +			builder.append(variant_defines[i].get_data()); + +			for (int j = 0; j < version->custom_defines.size(); j++) { +				builder.append(version->custom_defines[j].get_data()); +			} + +			builder.append(vertex_code0.get_data()); //first part of vertex + +			builder.append(version->uniforms.get_data()); //uniforms (same for vertex and fragment) + +			builder.append(vertex_code1.get_data()); //second part of vertex + +			builder.append(version->vertex_globals.get_data()); // vertex globals + +			builder.append(vertex_code2.get_data()); //third part of vertex + +			builder.append(version->vertex_code.get_data()); // code + +			builder.append(vertex_code3.get_data()); //fourth of vertex + +			RS::ShaderNativeSourceCode::Version::Stage stage; +			stage.name = "vertex"; +			stage.code = builder.as_string(); + +			source_code.versions.write[i].stages.push_back(stage); +		} + +		if (!is_compute) { +			//fragment stage + +			StringBuilder builder; + +			builder.append(fragment_codev.get_data()); // version info (if exists) +			builder.append("\n"); //make sure defines begin at newline + +			builder.append(general_defines.get_data()); +			builder.append(variant_defines[i].get_data()); +			for (int j = 0; j < version->custom_defines.size(); j++) { +				builder.append(version->custom_defines[j].get_data()); +			} + +			builder.append(fragment_code0.get_data()); //first part of fragment + +			builder.append(version->uniforms.get_data()); //uniforms (same for fragment and fragment) + +			builder.append(fragment_code1.get_data()); //first part of fragment + +			builder.append(version->fragment_globals.get_data()); // fragment globals + +			builder.append(fragment_code2.get_data()); //third part of fragment + +			builder.append(version->fragment_light.get_data()); // fragment light + +			builder.append(fragment_code3.get_data()); //fourth part of fragment + +			builder.append(version->fragment_code.get_data()); // fragment code + +			builder.append(fragment_code4.get_data()); //fourth part of fragment + +			RS::ShaderNativeSourceCode::Version::Stage stage; +			stage.name = "fragment"; +			stage.code = builder.as_string(); + +			source_code.versions.write[i].stages.push_back(stage); +		} + +		if (is_compute) { +			//compute stage + +			StringBuilder builder; + +			builder.append(compute_codev.get_data()); // version info (if exists) +			builder.append("\n"); //make sure defines begin at newline +			builder.append(general_defines.get_data()); +			builder.append(variant_defines[i].get_data()); + +			for (int j = 0; j < version->custom_defines.size(); j++) { +				builder.append(version->custom_defines[j].get_data()); +			} + +			builder.append(compute_code0.get_data()); //first part of compute + +			builder.append(version->uniforms.get_data()); //uniforms (same for compute and fragment) + +			builder.append(compute_code1.get_data()); //second part of compute + +			builder.append(version->compute_globals.get_data()); // compute globals + +			builder.append(compute_code2.get_data()); //third part of compute + +			builder.append(version->compute_code.get_data()); // code + +			builder.append(compute_code3.get_data()); //fourth of compute + +			RS::ShaderNativeSourceCode::Version::Stage stage; +			stage.name = "compute"; +			stage.code = builder.as_string(); + +			source_code.versions.write[i].stages.push_back(stage); +		} +	} + +	return source_code; +} +  void ShaderRD::_compile_version(Version *p_version) {  	_clear_version(p_version); @@ -360,7 +481,7 @@ void ShaderRD::_compile_version(Version *p_version) {  	p_version->variants = memnew_arr(RID, variant_defines.size());  #if 1 -	RendererCompositorRD::thread_work_pool.do_work(variant_defines.size(), this, &ShaderRD::_compile_variant, p_version); +	RendererThreadPool::singleton->thread_work_pool.do_work(variant_defines.size(), this, &ShaderRD::_compile_variant, p_version);  #else  	for (int i = 0; i < variant_defines.size(); i++) {  		_compile_variant(i, p_version); diff --git a/servers/rendering/renderer_rd/shader_rd.h b/servers/rendering/renderer_rd/shader_rd.h index a80d08050a..a3474c6f93 100644 --- a/servers/rendering/renderer_rd/shader_rd.h +++ b/servers/rendering/renderer_rd/shader_rd.h @@ -36,6 +36,7 @@  #include "core/templates/map.h"  #include "core/templates/rid_owner.h"  #include "core/variant/variant.h" +#include "servers/rendering_server.h"  #include <stdio.h>  /** @@ -133,6 +134,8 @@ public:  	void set_variant_enabled(int p_variant, bool p_enabled);  	bool is_variant_enabled(int p_variant) const; +	RS::ShaderNativeSourceCode version_get_native_source_code(RID p_version); +  	void initialize(const Vector<String> &p_variant_defines, const String &p_general_defines = "");  	virtual ~ShaderRD();  }; diff --git a/servers/rendering/renderer_rd/shaders/giprobe.glsl b/servers/rendering/renderer_rd/shaders/giprobe.glsl index ea4237a45e..4f4753d147 100644 --- a/servers/rendering/renderer_rd/shaders/giprobe.glsl +++ b/servers/rendering/renderer_rd/shaders/giprobe.glsl @@ -208,6 +208,15 @@ float raymarch(float distance, float distance_adv, vec3 from, vec3 direction) {  	return occlusion; //max(0.0,distance);  } +float get_omni_attenuation(float distance, float inv_range, float decay) { +	float nd = distance * inv_range; +	nd *= nd; +	nd *= nd; // nd^4 +	nd = max(1.0 - nd, 0.0); +	nd *= nd; // nd^2 +	return nd * pow(max(distance, 0.0001), -decay); +} +  bool compute_light_vector(uint light, vec3 pos, out float attenuation, out vec3 light_pos) {  	if (lights.data[light].type == LIGHT_TYPE_DIRECTIONAL) {  		light_pos = pos - lights.data[light].direction * length(vec3(params.limits)); @@ -220,7 +229,7 @@ bool compute_light_vector(uint light, vec3 pos, out float attenuation, out vec3  			return false;  		} -		attenuation = pow(clamp(1.0 - distance / lights.data[light].radius, 0.0001, 1.0), lights.data[light].attenuation); +		attenuation = get_omni_attenuation(distance, 1.0 / lights.data[light].radius, lights.data[light].attenuation);  		if (lights.data[light].type == LIGHT_TYPE_SPOT) {  			vec3 rel = normalize(pos - light_pos); diff --git a/servers/rendering/renderer_rd/shaders/scene_forward.glsl b/servers/rendering/renderer_rd/shaders/scene_forward.glsl index 1c12a8a4c7..0518976322 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward.glsl @@ -97,8 +97,6 @@ VERTEX_SHADER_GLOBALS  invariant gl_Position; -layout(location = 7) flat out uint instance_index; -  #ifdef MODE_DUAL_PARABOLOID  layout(location = 8) out float dp_clip; @@ -106,22 +104,27 @@ layout(location = 8) out float dp_clip;  #endif  void main() { -	instance_index = draw_call.instance_index;  	vec4 instance_custom = vec4(0.0);  #if defined(COLOR_USED)  	color_interp = color_attrib;  #endif -	mat4 world_matrix = instances.data[instance_index].transform; -	mat3 world_normal_matrix = mat3(instances.data[instance_index].normal_transform); +	mat4 world_matrix = draw_call.transform; -	if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH)) { +	mat3 world_normal_matrix; +	if (bool(draw_call.flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) { +		world_normal_matrix = inverse(mat3(world_matrix)); +	} else { +		world_normal_matrix = mat3(world_matrix); +	} + +	if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH)) {  		//multimesh, instances are for it -		uint offset = (instances.data[instance_index].flags >> INSTANCE_FLAGS_MULTIMESH_STRIDE_SHIFT) & INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK; +		uint offset = (draw_call.flags >> INSTANCE_FLAGS_MULTIMESH_STRIDE_SHIFT) & INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK;  		offset *= gl_InstanceIndex;  		mat4 matrix; -		if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) { +		if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) {  			matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));  			offset += 2;  		} else { @@ -129,14 +132,14 @@ void main() {  			offset += 3;  		} -		if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) { +		if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) {  #ifdef COLOR_USED  			color_interp *= transforms.data[offset];  #endif  			offset += 1;  		} -		if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) { +		if (bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) {  			instance_custom = transforms.data[offset];  		} @@ -144,10 +147,6 @@ void main() {  		matrix = transpose(matrix);  		world_matrix = world_matrix * matrix;  		world_normal_matrix = world_normal_matrix * mat3(matrix); - -	} else { -		//not a multimesh, instances are for multiple draw calls -		instance_index += gl_InstanceIndex;  	}  	vec3 vertex = vertex_attrib; @@ -162,7 +161,7 @@ void main() {  #endif  #if 0 -	if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_SKELETON)) { +	if (bool(draw_call.flags & INSTANCE_FLAGS_SKELETON)) {  		//multimesh, instances are for it  		uvec2 bones_01 = uvec2(bone_attrib.x & 0xFFFF, bone_attrib.x >> 16) * 3; @@ -305,7 +304,7 @@ VERTEX_SHADER_CODE  #endif  #ifdef MODE_RENDER_MATERIAL  	if (scene_data.material_uv2_mode) { -		gl_Position.xy = (uv2_attrib.xy + draw_call.bake_uv2_offset) * 2.0 - 1.0; +		gl_Position.xy = (uv2_attrib.xy + draw_call.lightmap_uv_scale.xy) * 2.0 - 1.0;  		gl_Position.z = 0.00001;  		gl_Position.w = 1.0;  	} @@ -345,8 +344,6 @@ layout(location = 5) in vec3 tangent_interp;  layout(location = 6) in vec3 binormal_interp;  #endif -layout(location = 7) flat in uint instance_index; -  #ifdef MODE_DUAL_PARABOLOID  layout(location = 8) in float dp_clip; @@ -355,8 +352,7 @@ layout(location = 8) in float dp_clip;  //defines to keep compatibility with vertex -#define world_matrix instances.data[instance_index].transform -#define world_normal_matrix instances.data[instance_index].normal_transform +#define world_matrix draw_call.transform  #define projection_matrix scene_data.projection_matrix  #if defined(ENABLE_SSS) && defined(ENABLE_TRANSMITTANCE) @@ -895,6 +891,15 @@ float sample_directional_soft_shadow(texture2D shadow, vec3 pssm_coord, vec2 tex  #endif //USE_NO_SHADOWS +float get_omni_attenuation(float distance, float inv_range, float decay) { +	float nd = distance * inv_range; +	nd *= nd; +	nd *= nd; // nd^4 +	nd = max(1.0 - nd, 0.0); +	nd *= nd; // nd^2 +	return nd * pow(max(distance, 0.0001), -decay); +} +  void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 albedo, float roughness, float metallic, float specular, float p_blob_intensity,  #ifdef LIGHT_BACKLIGHT_USED  		vec3 backlight, @@ -920,9 +925,8 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v  		inout vec3 diffuse_light, inout vec3 specular_light) {  	vec3 light_rel_vec = lights.data[idx].position - vertex;  	float light_length = length(light_rel_vec); -	float normalized_distance = light_length * lights.data[idx].inv_radius;  	vec2 attenuation_energy = unpackHalf2x16(lights.data[idx].attenuation_energy); -	float omni_attenuation = pow(max(1.0 - normalized_distance, 0.0), attenuation_energy.x); +	float omni_attenuation = get_omni_attenuation(light_length, lights.data[idx].inv_radius, attenuation_energy.x);  	float light_attenuation = omni_attenuation;  	vec3 shadow_attenuation = vec3(1.0);  	vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular); @@ -1209,9 +1213,8 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v  		inout vec3 specular_light) {  	vec3 light_rel_vec = lights.data[idx].position - vertex;  	float light_length = length(light_rel_vec); -	float normalized_distance = light_length * lights.data[idx].inv_radius;  	vec2 attenuation_energy = unpackHalf2x16(lights.data[idx].attenuation_energy); -	float spot_attenuation = pow(max(1.0 - normalized_distance, 0.001), attenuation_energy.x); +	float spot_attenuation = get_omni_attenuation(light_length, lights.data[idx].inv_radius, attenuation_energy.x);  	vec3 spot_dir = lights.data[idx].direction;  	vec2 spot_att_angle = unpackHalf2x16(lights.data[idx].cone_attenuation_angle);  	float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_att_angle.y); @@ -1971,7 +1974,7 @@ FRAGMENT_SHADER_CODE  		for (uint i = 0; i < decal_count; i++) {  			uint decal_index = cluster_data.indices[decal_pointer + i]; -			if (!bool(decals.data[decal_index].mask & instances.data[instance_index].layer_mask)) { +			if (!bool(decals.data[decal_index].mask & draw_call.layer_mask)) {  				continue; //not masked  			} @@ -2102,8 +2105,8 @@ FRAGMENT_SHADER_CODE  #ifdef USE_LIGHTMAP  	//lightmap -	if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE)) { //has lightmap capture -		uint index = instances.data[instance_index].gi_offset; +	if (bool(draw_call.flags & INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE)) { //has lightmap capture +		uint index = draw_call.gi_offset;  		vec3 wnormal = mat3(scene_data.camera_matrix) * normal;  		const float c1 = 0.429043; @@ -2122,12 +2125,12 @@ FRAGMENT_SHADER_CODE  						  2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y +  						  2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z); -	} else if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap -		bool uses_sh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP); -		uint ofs = instances.data[instance_index].gi_offset & 0xFFF; +	} else if (bool(draw_call.flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap +		bool uses_sh = bool(draw_call.flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP); +		uint ofs = draw_call.gi_offset & 0xFFFF;  		vec3 uvw; -		uvw.xy = uv2 * instances.data[instance_index].lightmap_uv_scale.zw + instances.data[instance_index].lightmap_uv_scale.xy; -		uvw.z = float((instances.data[instance_index].gi_offset >> 12) & 0xFF); +		uvw.xy = uv2 * draw_call.lightmap_uv_scale.zw + draw_call.lightmap_uv_scale.xy; +		uvw.z = float((draw_call.gi_offset >> 16) & 0xFFFF);  		if (uses_sh) {  			uvw.z *= 4.0; //SH textures use 4 times more data @@ -2136,7 +2139,7 @@ FRAGMENT_SHADER_CODE  			vec3 lm_light_l1_0 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 2.0), 0.0).rgb;  			vec3 lm_light_l1p1 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 3.0), 0.0).rgb; -			uint idx = instances.data[instance_index].gi_offset >> 20; +			uint idx = draw_call.gi_offset >> 20;  			vec3 n = normalize(lightmaps.data[idx].normal_xform * normal);  			ambient_light += lm_light_l0 * 0.282095f; @@ -2156,7 +2159,7 @@ FRAGMENT_SHADER_CODE  	}  #elif defined(USE_FORWARD_GI) -	if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SDFGI)) { //has lightmap capture +	if (bool(draw_call.flags & INSTANCE_FLAGS_USE_SDFGI)) { //has lightmap capture  		//make vertex orientation the world one, but still align to camera  		vec3 cam_pos = mat3(scene_data.camera_matrix) * vertex; @@ -2228,9 +2231,9 @@ FRAGMENT_SHADER_CODE  		}  	} -	if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes +	if (bool(draw_call.flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes -		uint index1 = instances.data[instance_index].gi_offset & 0xFFFF; +		uint index1 = draw_call.gi_offset & 0xFFFF;  		vec3 ref_vec = normalize(reflect(normalize(vertex), 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); @@ -2242,7 +2245,7 @@ FRAGMENT_SHADER_CODE  		vec4 spec_accum = vec4(0.0);  		gi_probe_compute(index1, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum); -		uint index2 = instances.data[instance_index].gi_offset >> 16; +		uint index2 = draw_call.gi_offset >> 16;  		if (index2 != 0xFFFF) {  			gi_probe_compute(index2, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum); @@ -2261,7 +2264,7 @@ FRAGMENT_SHADER_CODE  	}  #elif !defined(LOW_END_MODE) -	if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GI_BUFFERS)) { //use GI buffers +	if (bool(draw_call.flags & INSTANCE_FLAGS_USE_GI_BUFFERS)) { //use GI buffers  		ivec2 coord; @@ -2343,7 +2346,7 @@ FRAGMENT_SHADER_CODE  	{ //directional light  		for (uint i = 0; i < scene_data.directional_light_count; i++) { -			if (!bool(directional_lights.data[i].mask & instances.data[instance_index].layer_mask)) { +			if (!bool(directional_lights.data[i].mask & draw_call.layer_mask)) {  				continue; //not masked  			} @@ -2613,7 +2616,7 @@ FRAGMENT_SHADER_CODE  		for (uint i = 0; i < omni_light_count; i++) {  			uint light_index = cluster_data.indices[omni_light_pointer + i]; -			if (!bool(lights.data[light_index].mask & instances.data[instance_index].layer_mask)) { +			if (!bool(lights.data[light_index].mask & draw_call.layer_mask)) {  				continue; //not masked  			} @@ -2651,7 +2654,7 @@ FRAGMENT_SHADER_CODE  		for (uint i = 0; i < spot_light_count; i++) {  			uint light_index = cluster_data.indices[spot_light_pointer + i]; -			if (!bool(lights.data[light_index].mask & instances.data[instance_index].layer_mask)) { +			if (!bool(lights.data[light_index].mask & draw_call.layer_mask)) {  				continue; //not masked  			} @@ -2822,9 +2825,9 @@ FRAGMENT_SHADER_CODE  	normal_roughness_output_buffer = vec4(normal * 0.5 + 0.5, roughness);  #ifdef MODE_RENDER_GIPROBE -	if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes -		uint index1 = instances.data[instance_index].gi_offset & 0xFFFF; -		uint index2 = instances.data[instance_index].gi_offset >> 16; +	if (bool(draw_call.flags & INSTANCE_FLAGS_USE_GIPROBE)) { // process giprobes +		uint index1 = draw_call.gi_offset & 0xFFFF; +		uint index2 = draw_call.gi_offset >> 16;  		giprobe_buffer.x = index1 & 0xFF;  		giprobe_buffer.y = index2 & 0xFF;  	} else { diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_inc.glsl index 17ed22f58a..87ce74ba88 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_inc.glsl @@ -12,9 +12,12 @@  #endif  layout(push_constant, binding = 0, std430) uniform DrawCall { -	uint instance_index; -	uint pad; //16 bits minimum size -	vec2 bake_uv2_offset; //used for bake to uv2, ignored otherwise +	mat4 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) +	uint layer_mask; +	vec4 lightmap_uv_scale;  }  draw_call; @@ -134,21 +137,7 @@ scene_data;  #define INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK 0x7  #define INSTANCE_FLAGS_SKELETON (1 << 19) - -struct InstanceData { -	mat4 transform; -	mat4 normal_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) -	uint layer_mask; -	vec4 lightmap_uv_scale; -}; - -layout(set = 0, binding = 4, std430) restrict readonly buffer Instances { -	InstanceData data[]; -} -instances; +#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 20)  layout(set = 0, binding = 5, std430) restrict readonly buffer Lights {  	LightData data[]; @@ -177,35 +166,33 @@ layout(set = 0, binding = 10, std140) restrict readonly buffer Lightmaps {  }  lightmaps; -layout(set = 0, binding = 11) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES]; -  struct LightmapCapture {  	vec4 sh[9];  }; -layout(set = 0, binding = 12, std140) restrict readonly buffer LightmapCaptures { +layout(set = 0, binding = 11, std140) restrict readonly buffer LightmapCaptures {  	LightmapCapture data[];  }  lightmap_captures; -layout(set = 0, binding = 13) uniform texture2D decal_atlas; -layout(set = 0, binding = 14) uniform texture2D decal_atlas_srgb; +layout(set = 0, binding = 12) uniform texture2D decal_atlas; +layout(set = 0, binding = 13) uniform texture2D decal_atlas_srgb; -layout(set = 0, binding = 15, std430) restrict readonly buffer Decals { +layout(set = 0, binding = 14, std430) restrict readonly buffer Decals {  	DecalData data[];  }  decals; -layout(set = 0, binding = 16) uniform utexture3D cluster_texture; +layout(set = 0, binding = 15) uniform utexture3D cluster_texture; -layout(set = 0, binding = 17, std430) restrict readonly buffer ClusterData { +layout(set = 0, binding = 16, std430) restrict readonly buffer ClusterData {  	uint indices[];  }  cluster_data; -layout(set = 0, binding = 18) uniform texture2D directional_shadow_atlas; +layout(set = 0, binding = 17) uniform texture2D directional_shadow_atlas; -layout(set = 0, binding = 19, std430) restrict readonly buffer GlobalVariableData { +layout(set = 0, binding = 18, std430) restrict readonly buffer GlobalVariableData {  	vec4 data[];  }  global_variables; @@ -219,7 +206,7 @@ struct SDFGIProbeCascadeData {  	float to_cell; // 1/bounds * grid_size  }; -layout(set = 0, binding = 20, std140) uniform SDFGI { +layout(set = 0, binding = 19, std140) uniform SDFGI {  	vec3 grid_size;  	uint max_cascades; @@ -269,18 +256,20 @@ layout(set = 1, binding = 1) uniform textureCubeArray reflection_atlas;  layout(set = 1, binding = 2) uniform texture2D shadow_atlas; +layout(set = 1, binding = 3) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES]; +  #ifndef LOW_END_MODE -layout(set = 1, binding = 3) uniform texture3D gi_probe_textures[MAX_GI_PROBES]; +layout(set = 1, binding = 4) uniform texture3D gi_probe_textures[MAX_GI_PROBES];  #endif  /* Set 3, Render Buffers */  #ifdef MODE_RENDER_SDF -layout(r16ui, set = 1, binding = 4) uniform restrict writeonly uimage3D albedo_volume_grid; -layout(r32ui, set = 1, binding = 5) uniform restrict writeonly uimage3D emission_grid; -layout(r32ui, set = 1, binding = 6) uniform restrict writeonly uimage3D emission_aniso_grid; -layout(r32ui, set = 1, binding = 7) uniform restrict uimage3D geom_facing_grid; +layout(r16ui, set = 1, binding = 5) uniform restrict writeonly uimage3D albedo_volume_grid; +layout(r32ui, set = 1, binding = 6) uniform restrict writeonly uimage3D emission_grid; +layout(r32ui, set = 1, binding = 7) uniform restrict writeonly uimage3D emission_aniso_grid; +layout(r32ui, set = 1, binding = 8) uniform restrict uimage3D geom_facing_grid;  //still need to be present for shaders that use it, so remap them to something  #define depth_buffer shadow_atlas @@ -289,17 +278,17 @@ layout(r32ui, set = 1, binding = 7) uniform restrict uimage3D geom_facing_grid;  #else -layout(set = 1, binding = 4) uniform texture2D depth_buffer; -layout(set = 1, binding = 5) uniform texture2D color_buffer; +layout(set = 1, binding = 5) uniform texture2D depth_buffer; +layout(set = 1, binding = 6) uniform texture2D color_buffer;  #ifndef LOW_END_MODE -layout(set = 1, binding = 6) uniform texture2D normal_roughness_buffer; -layout(set = 1, binding = 7) uniform texture2D ao_buffer; -layout(set = 1, binding = 8) uniform texture2D ambient_buffer; -layout(set = 1, binding = 9) uniform texture2D reflection_buffer; -layout(set = 1, binding = 10) uniform texture2DArray sdfgi_lightprobe_texture; -layout(set = 1, binding = 11) uniform texture3D sdfgi_occlusion_cascades; +layout(set = 1, binding = 7) uniform texture2D normal_roughness_buffer; +layout(set = 1, binding = 8) uniform texture2D ao_buffer; +layout(set = 1, binding = 9) uniform texture2D ambient_buffer; +layout(set = 1, binding = 10) uniform texture2D reflection_buffer; +layout(set = 1, binding = 11) uniform texture2DArray sdfgi_lightprobe_texture; +layout(set = 1, binding = 12) uniform texture3D sdfgi_occlusion_cascades;  struct GIProbeData {  	mat4 xform; @@ -317,12 +306,12 @@ struct GIProbeData {  	uint mipmaps;  }; -layout(set = 1, binding = 12, std140) uniform GIProbes { +layout(set = 1, binding = 13, std140) uniform GIProbes {  	GIProbeData data[MAX_GI_PROBES];  }  gi_probes; -layout(set = 1, binding = 13) uniform texture3D volumetric_fog_texture; +layout(set = 1, binding = 14) uniform texture3D volumetric_fog_texture;  #endif // LOW_END_MODE diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl b/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl index 61e4bf5e18..30dbf5871f 100644 --- a/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl +++ b/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl @@ -112,6 +112,15 @@ vec2 octahedron_encode(vec3 n) {  	return n.xy;  } +float get_omni_attenuation(float distance, float inv_range, float decay) { +	float nd = distance * inv_range; +	nd *= nd; +	nd *= nd; // nd^4 +	nd = max(1.0 - nd, 0.0); +	nd *= nd; // nd^2 +	return nd * pow(max(distance, 0.0001), -decay); +} +  void main() {  	uint voxel_index = uint(gl_GlobalInvocationID.x); @@ -184,14 +193,15 @@ void main() {  				direction = normalize(rel_vec);  				light_distance = length(rel_vec);  				rel_vec.y /= params.y_mult; -				attenuation = pow(clamp(1.0 - length(rel_vec) / lights.data[i].radius, 0.0, 1.0), lights.data[i].attenuation); +				attenuation = get_omni_attenuation(light_distance, 1.0 / lights.data[i].radius, lights.data[i].attenuation); +  			} break;  			case LIGHT_TYPE_SPOT: {  				vec3 rel_vec = lights.data[i].position - position;  				direction = normalize(rel_vec);  				light_distance = length(rel_vec);  				rel_vec.y /= params.y_mult; -				attenuation = pow(clamp(1.0 - length(rel_vec) / lights.data[i].radius, 0.0, 1.0), lights.data[i].attenuation); +				attenuation = get_omni_attenuation(light_distance, 1.0 / lights.data[i].radius, lights.data[i].attenuation);  				float angle = acos(dot(normalize(rel_vec), -lights.data[i].direction));  				if (angle > lights.data[i].spot_angle) { diff --git a/servers/rendering/renderer_rd/shaders/ssao.glsl b/servers/rendering/renderer_rd/shaders/ssao.glsl index 315ef8fa13..231f8f91ec 100644 --- a/servers/rendering/renderer_rd/shaders/ssao.glsl +++ b/servers/rendering/renderer_rd/shaders/ssao.glsl @@ -88,7 +88,7 @@ counter;  layout(rg8, set = 2, binding = 0) uniform restrict writeonly image2D dest_image;  // This push_constant is full - 128 bytes - if you need to add more data, consider adding to the uniform buffer instead -layout(push_constant, binding = 1, std430) uniform Params { +layout(push_constant, binding = 3, std430) uniform Params {  	ivec2 screen_size;  	int pass;  	int quality; diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl index 13b162f0c9..498a6ddb5b 100644 --- a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl +++ b/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl @@ -169,6 +169,15 @@ vec3 hash3f(uvec3 x) {  	return vec3(x & 0xFFFFF) / vec3(float(0xFFFFF));  } +float get_omni_attenuation(float distance, float inv_range, float decay) { +	float nd = distance * inv_range; +	nd *= nd; +	nd *= nd; // nd^4 +	nd = max(1.0 - nd, 0.0); +	nd *= nd; // nd^2 +	return nd * pow(max(distance, 0.0001), -decay); +} +  void main() {  	vec3 fog_cell_size = 1.0 / vec3(params.fog_volume_size); @@ -270,14 +279,14 @@ void main() {  		uint light_index = cluster_data.indices[omni_light_pointer + i];  		vec3 light_pos = lights.data[i].position; -		float d = distance(lights.data[i].position, view_pos) * lights.data[i].inv_radius; +		float d = distance(lights.data[i].position, view_pos);  		vec3 shadow_attenuation = vec3(1.0); -		if (d < 1.0) { +		if (d * lights.data[i].inv_radius < 1.0) {  			vec2 attenuation_energy = unpackHalf2x16(lights.data[i].attenuation_energy);  			vec4 color_specular = unpackUnorm4x8(lights.data[i].color_specular); -			float attenuation = pow(max(1.0 - d, 0.0), attenuation_energy.x); +			float attenuation = get_omni_attenuation(d, lights.data[i].inv_radius, attenuation_energy.x);  			vec3 light = attenuation_energy.y * color_specular.rgb / M_PI; @@ -326,14 +335,14 @@ void main() {  		vec3 light_pos = lights.data[i].position;  		vec3 light_rel_vec = lights.data[i].position - view_pos; -		float d = length(light_rel_vec) * lights.data[i].inv_radius; +		float d = length(light_rel_vec);  		vec3 shadow_attenuation = vec3(1.0); -		if (d < 1.0) { +		if (d * lights.data[i].inv_radius < 1.0) {  			vec2 attenuation_energy = unpackHalf2x16(lights.data[i].attenuation_energy);  			vec4 color_specular = unpackUnorm4x8(lights.data[i].color_specular); -			float attenuation = pow(max(1.0 - d, 0.0), attenuation_energy.x); +			float attenuation = get_omni_attenuation(d, lights.data[i].inv_radius, attenuation_energy.x);  			vec3 spot_dir = lights.data[i].direction;  			vec2 spot_att_angle = unpackHalf2x16(lights.data[i].cone_attenuation_angle);  |