diff options
Diffstat (limited to 'servers/rendering/renderer_rd')
| -rw-r--r-- | servers/rendering/renderer_rd/renderer_scene_render_forward.cpp | 466 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/renderer_scene_render_forward.h | 35 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/renderer_scene_render_rd.cpp | 268 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/renderer_scene_render_rd.h | 4 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shader_rd.cpp | 24 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shader_rd.h | 5 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/SCsub | 2 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/scene_forward.glsl (renamed from servers/rendering/renderer_rd/shaders/scene_high_end.glsl) | 41 | ||||
| -rw-r--r-- | servers/rendering/renderer_rd/shaders/scene_forward_inc.glsl (renamed from servers/rendering/renderer_rd/shaders/scene_high_end_inc.glsl) | 47 | 
9 files changed, 489 insertions, 403 deletions
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_forward.cpp b/servers/rendering/renderer_rd/renderer_scene_render_forward.cpp index d603d32de8..5412688e3f 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_forward.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_forward.cpp @@ -257,6 +257,9 @@ void RendererSceneRenderForward::ShaderData::set_code(const String &p_code) {  			RD::RenderPrimitive primitive_rd = uses_point_size ? RD::RENDER_PRIMITIVE_POINTS : primitive_rd_table[j];  			for (int k = 0; k < SHADER_VERSION_MAX; k++) { +				if (!static_cast<RendererSceneRenderForward *>(singleton)->shader.scene_shader.is_variant_enabled(k)) { +					continue; +				}  				RD::PipelineRasterizationState raster_state;  				raster_state.cull_mode = cull_mode_rd;  				raster_state.wireframe = wireframe; @@ -516,11 +519,11 @@ RendererStorageRD::MaterialData *RendererSceneRenderForward::_create_material_fu  	return material_data;  } -RendererSceneRenderForward::RenderBufferDataHighEnd::~RenderBufferDataHighEnd() { +RendererSceneRenderForward::RenderBufferDataForward::~RenderBufferDataForward() {  	clear();  } -void RendererSceneRenderForward::RenderBufferDataHighEnd::ensure_specular() { +void RendererSceneRenderForward::RenderBufferDataForward::ensure_specular() {  	if (!specular.is_valid()) {  		RD::TextureFormat tf;  		tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; @@ -574,7 +577,7 @@ void RendererSceneRenderForward::RenderBufferDataHighEnd::ensure_specular() {  	}  } -void RendererSceneRenderForward::RenderBufferDataHighEnd::ensure_gi() { +void RendererSceneRenderForward::RenderBufferDataForward::ensure_gi() {  	if (!reflection_buffer.is_valid()) {  		RD::TextureFormat tf;  		tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; @@ -587,7 +590,7 @@ void RendererSceneRenderForward::RenderBufferDataHighEnd::ensure_gi() {  	}  } -void RendererSceneRenderForward::RenderBufferDataHighEnd::ensure_giprobe() { +void RendererSceneRenderForward::RenderBufferDataForward::ensure_giprobe() {  	if (!giprobe_buffer.is_valid()) {  		RD::TextureFormat tf;  		tf.format = RD::DATA_FORMAT_R8G8_UINT; @@ -623,7 +626,7 @@ void RendererSceneRenderForward::RenderBufferDataHighEnd::ensure_giprobe() {  	}  } -void RendererSceneRenderForward::RenderBufferDataHighEnd::clear() { +void RendererSceneRenderForward::RenderBufferDataForward::clear() {  	if (ambient_buffer != RID() && ambient_buffer != color) {  		RD::get_singleton()->free(ambient_buffer);  		ambient_buffer = RID(); @@ -687,7 +690,7 @@ void RendererSceneRenderForward::RenderBufferDataHighEnd::clear() {  	}  } -void RendererSceneRenderForward::RenderBufferDataHighEnd::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa) { +void RendererSceneRenderForward::RenderBufferDataForward::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa) {  	clear();  	msaa = p_msaa; @@ -754,7 +757,7 @@ void RendererSceneRenderForward::RenderBufferDataHighEnd::configure(RID p_color_  	}  } -void RendererSceneRenderForward::_allocate_normal_roughness_texture(RenderBufferDataHighEnd *rb) { +void RendererSceneRenderForward::_allocate_normal_roughness_texture(RenderBufferDataForward *rb) {  	if (rb->normal_roughness_buffer.is_valid()) {  		return;  	} @@ -793,7 +796,7 @@ void RendererSceneRenderForward::_allocate_normal_roughness_texture(RenderBuffer  }  RendererSceneRenderRD::RenderBufferData *RendererSceneRenderForward::_create_render_buffer_data() { -	return memnew(RenderBufferDataHighEnd); +	return memnew(RenderBufferDataForward);  }  bool RendererSceneRenderForward::free(RID p_rid) { @@ -911,7 +914,7 @@ void RendererSceneRenderForward::_fill_instances(RenderList::Element **p_element  				id.flags |= INSTANCE_DATA_FLAG_USE_GI_BUFFERS;  			} -			if (!e->instance->gi_probe_instances.empty()) { +			if (!low_end && !e->instance->gi_probe_instances.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]; @@ -950,23 +953,13 @@ void RendererSceneRenderForward::_fill_instances(RenderList::Element **p_element  /// 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_radiance_uniform_set, RID p_render_buffers_uniform_set, bool p_force_wireframe, const Vector2 &p_uv_offset) { +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) {  	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); -	if (p_radiance_uniform_set.is_valid()) { -		RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_radiance_uniform_set, RADIANCE_UNIFORM_SET); -	} else { -		RD::get_singleton()->draw_list_bind_uniform_set(draw_list, default_radiance_uniform_set, RADIANCE_UNIFORM_SET); -	} -	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, view_dependant_uniform_set, VIEW_DEPENDANT_UNIFORM_SET); -	if (p_render_buffers_uniform_set.is_valid()) { -		RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_render_buffers_uniform_set, RENDER_BUFFERS_UNIFORM_SET); -	} else { -		RD::get_singleton()->draw_list_bind_uniform_set(draw_list, default_render_buffers_uniform_set, RENDER_BUFFERS_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, default_vec4_xform_uniform_set, TRANSFORMS_UNIFORM_SET);  	MaterialData *prev_material = nullptr; @@ -1214,7 +1207,7 @@ void RendererSceneRenderForward::_setup_environment(RID p_environment, RID p_ren  	scene_state.ubo.fog_enabled = false;  	if (p_render_buffers.is_valid()) { -		RenderBufferDataHighEnd *render_buffers = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); +		RenderBufferDataForward *render_buffers = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffers);  		if (render_buffers->msaa != RS::VIEWPORT_MSAA_DISABLED) {  			scene_state.ubo.gi_upscale_for_msaa = true;  		} @@ -1639,9 +1632,9 @@ void RendererSceneRenderForward::_setup_lightmaps(InstanceBase **p_lightmap_cull  }  void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, int p_directional_light_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, 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) { -	RenderBufferDataHighEnd *render_buffer = nullptr; +	RenderBufferDataForward *render_buffer = nullptr;  	if (p_render_buffer.is_valid()) { -		render_buffer = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffer); +		render_buffer = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffer);  	}  	//first of all, make a new render pass @@ -1686,7 +1679,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf  		opaque_framebuffer = render_buffer->color_fb; -		if (p_gi_probe_cull_count > 0) { +		if (!low_end && p_gi_probe_cull_count > 0) {  			using_giprobe = true;  			render_buffer->ensure_gi();  		} @@ -1761,7 +1754,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf  	render_list.clear();  	_fill_render_list(p_cull_result, p_cull_count, PASS_MODE_COLOR, using_sdfgi); -	bool using_sss = render_buffer && scene_state.used_sss && sub_surface_scattering_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED; +	bool using_sss = !low_end && render_buffer && scene_state.used_sss && sub_surface_scattering_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED;  	if (using_sss) {  		using_separate_specular = true; @@ -1769,7 +1762,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf  		using_separate_specular = true;  		opaque_specular_framebuffer = render_buffer->color_specular_fb;  	} -	RID radiance_uniform_set; +	RID radiance_texture;  	bool draw_sky = false;  	bool draw_sky_fog_only = false; @@ -1831,7 +1824,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf  			RID sky = environment_get_sky(p_environment);  			if (sky.is_valid()) {  				_update_sky(p_environment, projection, p_cam_transform); -				radiance_uniform_set = sky_get_radiance_uniform_set_rd(sky, default_shader_rd, RADIANCE_UNIFORM_SET); +				radiance_texture = sky_get_radiance_texture_rd(sky);  			} else {  				// do not try to draw sky if invalid  				draw_sky = false; @@ -1841,7 +1834,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf  		clear_color = p_default_bg_color;  	} -	_setup_view_dependant_uniform_set(p_shadow_atlas, p_reflection_atlas, p_gi_probe_cull_result, p_gi_probe_cull_count); +	RID rp_uniform_set = _setup_render_pass_uniform_set(p_render_buffer, radiance_texture, p_shadow_atlas, p_reflection_atlas, p_gi_probe_cull_result, p_gi_probe_cull_count);  	render_list.sort_by_key(false); @@ -1850,8 +1843,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf  	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; -	bool depth_pre_pass = depth_framebuffer.is_valid(); -	RID render_buffers_uniform_set; +	bool depth_pre_pass = !low_end && depth_framebuffer.is_valid();  	bool using_ssao = depth_pre_pass && p_render_buffer.is_valid() && p_environment.is_valid() && environment_is_ssao_enabled(p_environment);  	bool continue_depth = false; @@ -1860,7 +1852,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf  		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, radiance_uniform_set, RID(), get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME); +		_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);  		RD::get_singleton()->draw_list_end();  		if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) { @@ -1884,12 +1876,6 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf  		_process_gi(p_render_buffer, render_buffer->normal_roughness_buffer, render_buffer->ambient_buffer, render_buffer->reflection_buffer, render_buffer->giprobe_buffer, p_environment, p_cam_projection, p_cam_transform, p_gi_probe_cull_result, p_gi_probe_cull_count);  	} -	if (p_render_buffer.is_valid()) { -		//update the render buffers uniform set in case it changed -		_update_render_buffers_uniform_set(p_render_buffer); -		render_buffers_uniform_set = render_buffer->uniform_set; -	} -  	_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(), p_render_buffer.is_valid());  	RENDER_TIMESTAMP("Render Opaque Pass"); @@ -1914,7 +1900,7 @@ 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, radiance_uniform_set, render_buffers_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME); +		_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);  		RD::get_singleton()->draw_list_end();  		if (will_continue_color && using_separate_specular) { @@ -2002,7 +1988,7 @@ void RendererSceneRenderForward::_render_scene(RID p_render_buffer, const Transf  	{  		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, radiance_uniform_set, render_buffers_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME); +		_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);  		RD::get_singleton()->draw_list_end();  	} @@ -2028,7 +2014,7 @@ void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, InstanceBase  	_fill_render_list(p_cull_result, p_cull_count, pass_mode); -	_setup_view_dependant_uniform_set(RID(), RID(), nullptr, 0); +	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), nullptr, 0);  	RENDER_TIMESTAMP("Render Shadow"); @@ -2039,7 +2025,7 @@ void RendererSceneRenderForward::_render_shadow(RID p_framebuffer, InstanceBase  	{  		//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, RID(), RID()); +		_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);  		RD::get_singleton()->draw_list_end();  	}  } @@ -2061,7 +2047,7 @@ void RendererSceneRenderForward::_render_particle_collider_heightfield(RID p_fb,  	_fill_render_list(p_cull_result, p_cull_count, pass_mode); -	_setup_view_dependant_uniform_set(RID(), RID(), nullptr, 0); +	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), nullptr, 0);  	RENDER_TIMESTAMP("Render Collider Heightield"); @@ -2072,7 +2058,7 @@ void RendererSceneRenderForward::_render_particle_collider_heightfield(RID p_fb,  	{  		//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, RID(), RID()); +		_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();  	}  } @@ -2094,7 +2080,7 @@ void RendererSceneRenderForward::_render_material(const Transform &p_cam_transfo  	PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL;  	_fill_render_list(p_cull_result, p_cull_count, pass_mode); -	_setup_view_dependant_uniform_set(RID(), RID(), nullptr, 0); +	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), nullptr, 0);  	RENDER_TIMESTAMP("Render Material"); @@ -2111,7 +2097,7 @@ 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, RID(), RID()); +		_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);  		RD::get_singleton()->draw_list_end();  	}  } @@ -2133,7 +2119,7 @@ void RendererSceneRenderForward::_render_uv2(InstanceBase **p_cull_result, int p  	PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL;  	_fill_render_list(p_cull_result, p_cull_count, pass_mode); -	_setup_view_dependant_uniform_set(RID(), RID(), nullptr, 0); +	RID rp_uniform_set = _setup_render_pass_uniform_set(RID(), RID(), RID(), RID(), nullptr, 0);  	RENDER_TIMESTAMP("Render Material"); @@ -2169,9 +2155,9 @@ void RendererSceneRenderForward::_render_uv2(InstanceBase **p_cull_result, int 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, RID(), RID(), true, ofs); //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, true, ofs); //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, RID(), RID(), false); //second regular triangles +		_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  		RD::get_singleton()->draw_list_end();  	} @@ -2182,7 +2168,7 @@ void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vecto  	_update_render_base_uniform_set(); -	RenderBufferDataHighEnd *render_buffer = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); +	RenderBufferDataForward *render_buffer = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffers);  	ERR_FAIL_COND(!render_buffer);  	render_pass++; @@ -2193,45 +2179,11 @@ void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vecto  	render_list.sort_by_key(false);  	_fill_instances(render_list.elements, render_list.element_count, true); -	_setup_view_dependant_uniform_set(RID(), RID(), nullptr, 0); +	RID rp_uniform_set = _setup_sdfgi_render_pass_uniform_set(p_albedo_texture, p_emission_texture, p_emission_aniso_texture, p_geom_facing_texture);  	Vector3 half_extents = p_bounds.size * 0.5;  	Vector3 center = p_bounds.position + half_extents; -	if (render_buffer->render_sdfgi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_buffer->render_sdfgi_uniform_set)) { -		Vector<RD::Uniform> uniforms; -		{ -			RD::Uniform u; -			u.uniform_type = RD::UNIFORM_TYPE_IMAGE; -			u.binding = 0; -			u.ids.push_back(p_albedo_texture); -			uniforms.push_back(u); -		} -		{ -			RD::Uniform u; -			u.uniform_type = RD::UNIFORM_TYPE_IMAGE; -			u.binding = 1; -			u.ids.push_back(p_emission_texture); -			uniforms.push_back(u); -		} -		{ -			RD::Uniform u; -			u.uniform_type = RD::UNIFORM_TYPE_IMAGE; -			u.binding = 2; -			u.ids.push_back(p_emission_aniso_texture); -			uniforms.push_back(u); -		} -		{ -			RD::Uniform u; -			u.uniform_type = RD::UNIFORM_TYPE_IMAGE; -			u.binding = 3; -			u.ids.push_back(p_geom_facing_texture); -			uniforms.push_back(u); -		} - -		render_buffer->render_sdfgi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_sdfgi_rd, RENDER_BUFFERS_UNIFORM_SET); -	} -  	Vector<RID> sbs;  	sbs.push_back(p_albedo_texture);  	sbs.push_back(p_emission_texture); @@ -2287,7 +2239,7 @@ void RendererSceneRenderForward::_render_sdfgi(RID p_render_buffers, const Vecto  		}  		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, RID(), render_buffer->render_sdfgi_uniform_set, false); //second regular triangles +		_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();  	}  } @@ -2455,7 +2407,7 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {  			uniforms.push_back(u);  		} -		{ +		if (!low_end) {  			RD::Uniform u;  			u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;  			u.binding = 20; @@ -2467,9 +2419,14 @@ void RendererSceneRenderForward::_update_render_base_uniform_set() {  	}  } -void RendererSceneRenderForward::_setup_view_dependant_uniform_set(RID p_shadow_atlas, RID p_reflection_atlas, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count) { -	if (view_dependant_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(view_dependant_uniform_set)) { -		RD::get_singleton()->free(view_dependant_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, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count) { +	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); +	} + +	RenderBufferDataForward *rb = nullptr; +	if (p_render_buffers.is_valid()) { +		rb = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffers);  	}  	//default render buffer and scene state uniform set @@ -2477,10 +2434,24 @@ void RendererSceneRenderForward::_setup_view_dependant_uniform_set(RID p_shadow_  	Vector<RD::Uniform> uniforms;  	{ -		RID ref_texture = p_reflection_atlas.is_valid() ? reflection_atlas_get_texture(p_reflection_atlas) : RID(); +		RID radiance_texture; +		if (p_radiance_texture.is_valid()) { +			radiance_texture = p_radiance_texture; +		} else { +			radiance_texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); +		}  		RD::Uniform u;  		u.binding = 0;  		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; +		u.ids.push_back(radiance_texture); +		uniforms.push_back(u); +	} + +	{ +		RID ref_texture = p_reflection_atlas.is_valid() ? reflection_atlas_get_texture(p_reflection_atlas) : RID(); +		RD::Uniform u; +		u.binding = 1; +		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  		if (ref_texture.is_valid()) {  			u.ids.push_back(ref_texture);  		} else { @@ -2491,7 +2462,7 @@ void RendererSceneRenderForward::_setup_view_dependant_uniform_set(RID p_shadow_  	{  		RD::Uniform u; -		u.binding = 1; +		u.binding = 2;  		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  		RID texture;  		if (p_shadow_atlas.is_valid()) { @@ -2506,8 +2477,9 @@ void RendererSceneRenderForward::_setup_view_dependant_uniform_set(RID p_shadow_  	{  		RD::Uniform u; -		u.binding = 2; +		u.binding = 3;  		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++) {  			if (i < p_gi_probe_cull_count) { @@ -2515,84 +2487,47 @@ void RendererSceneRenderForward::_setup_view_dependant_uniform_set(RID p_shadow_  				if (!tex.is_valid()) {  					tex = default_tex;  				} -				u.ids.push_back(tex); +				u.ids.write[i] = tex;  			} else { -				u.ids.push_back(default_tex); +				u.ids.write[i] = default_tex;  			}  		}  		uniforms.push_back(u);  	} -	view_dependant_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, VIEW_DEPENDANT_UNIFORM_SET); -} -void RendererSceneRenderForward::_render_buffers_clear_uniform_set(RenderBufferDataHighEnd *rb) { -	if (!rb->uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(rb->uniform_set)) { -		RD::get_singleton()->free(rb->uniform_set); +	{ +		RD::Uniform u; +		u.binding = 4; +		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); +		uniforms.push_back(u);  	} -	rb->uniform_set = RID(); -} - -void RendererSceneRenderForward::_render_buffers_uniform_set_changed(RID p_render_buffers) { -	RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); - -	_render_buffers_clear_uniform_set(rb); -} - -RID RendererSceneRenderForward::_render_buffers_get_normal_texture(RID p_render_buffers) { -	RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); - -	return rb->normal_roughness_buffer; -} - -RID RendererSceneRenderForward::_render_buffers_get_ambient_texture(RID p_render_buffers) { -	RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); - -	return rb->ambient_buffer; -} - -RID RendererSceneRenderForward::_render_buffers_get_reflection_texture(RID p_render_buffers) { -	RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); - -	return rb->reflection_buffer; -} - -void RendererSceneRenderForward::_update_render_buffers_uniform_set(RID p_render_buffers) { -	RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); - -	if (rb->uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->uniform_set)) { -		Vector<RD::Uniform> uniforms; -		{ -			RD::Uniform u; -			u.binding = 0; -			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; -			RID texture = false && rb->depth.is_valid() ? rb->depth : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); -			u.ids.push_back(texture); -			uniforms.push_back(u); -		} -		{ -			RD::Uniform u; -			u.binding = 1; -			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; -			RID bbt = render_buffers_get_back_buffer_texture(p_render_buffers); -			RID texture = bbt.is_valid() ? bbt : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); -			u.ids.push_back(texture); -			uniforms.push_back(u); -		} +	{ +		RD::Uniform u; +		u.binding = 5; +		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); +		u.ids.push_back(texture); +		uniforms.push_back(u); +	} +	if (!low_end) {  		{  			RD::Uniform u; -			u.binding = 2; +			u.binding = 6;  			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; -			RID texture = rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_NORMAL); +			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);  			uniforms.push_back(u);  		}  		{  			RD::Uniform u; -			u.binding = 4; +			u.binding = 7;  			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; -			RID aot = render_buffers_get_ao_texture(p_render_buffers); +			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);  			u.ids.push_back(texture);  			uniforms.push_back(u); @@ -2600,27 +2535,27 @@ void RendererSceneRenderForward::_update_render_buffers_uniform_set(RID p_render  		{  			RD::Uniform u; -			u.binding = 5; +			u.binding = 8;  			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; -			RID texture = rb->ambient_buffer.is_valid() ? rb->ambient_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); +			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);  			uniforms.push_back(u);  		}  		{  			RD::Uniform u; -			u.binding = 6; +			u.binding = 9;  			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; -			RID texture = rb->reflection_buffer.is_valid() ? rb->reflection_buffer : storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK); +			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);  			uniforms.push_back(u);  		}  		{  			RD::Uniform u; -			u.binding = 7; +			u.binding = 10;  			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  			RID t; -			if (render_buffers_is_sdfgi_enabled(p_render_buffers)) { +			if (rb && render_buffers_is_sdfgi_enabled(p_render_buffers)) {  				t = render_buffers_get_sdfgi_irradiance_probes(p_render_buffers);  			} else {  				t = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); @@ -2630,9 +2565,9 @@ void RendererSceneRenderForward::_update_render_buffers_uniform_set(RID p_render  		}  		{  			RD::Uniform u; -			u.binding = 8; +			u.binding = 11;  			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; -			if (render_buffers_is_sdfgi_enabled(p_render_buffers)) { +			if (rb && render_buffers_is_sdfgi_enabled(p_render_buffers)) {  				u.ids.push_back(render_buffers_get_sdfgi_occlusion_texture(p_render_buffers));  			} else {  				u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); @@ -2641,17 +2576,17 @@ void RendererSceneRenderForward::_update_render_buffers_uniform_set(RID p_render  		}  		{  			RD::Uniform u; -			u.binding = 9; +			u.binding = 12;  			u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; -			u.ids.push_back(render_buffers_get_gi_probe_buffer(p_render_buffers)); +			u.ids.push_back(rb ? render_buffers_get_default_gi_probe_buffer() : render_buffers_get_gi_probe_buffer(p_render_buffers));  			uniforms.push_back(u);  		}  		{  			RD::Uniform u; -			u.binding = 10; +			u.binding = 13;  			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;  			RID vfog = RID(); -			if (p_render_buffers.is_valid() && render_buffers_has_volumetric_fog(p_render_buffers)) { +			if (rb && render_buffers_has_volumetric_fog(p_render_buffers)) {  				vfog = render_buffers_get_volumetric_fog_texture(p_render_buffers);  				if (vfog.is_null()) {  					vfog = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); @@ -2662,8 +2597,122 @@ void RendererSceneRenderForward::_update_render_buffers_uniform_set(RID p_render  			u.ids.push_back(vfog);  			uniforms.push_back(u);  		} -		rb->uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, RENDER_BUFFERS_UNIFORM_SET);  	} + +	render_pass_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, RENDER_PASS_UNIFORM_SET); +	return render_pass_uniform_set; +} + +RID RendererSceneRenderForward::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture) { +	if (sdfgi_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sdfgi_pass_uniform_set)) { +		RD::get_singleton()->free(sdfgi_pass_uniform_set); +	} + +	Vector<RD::Uniform> uniforms; + +	{ +		// No radiance texture. +		RID radiance_texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); +		RD::Uniform u; +		u.binding = 0; +		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; +		u.ids.push_back(radiance_texture); +		uniforms.push_back(u); +	} + +	{ +		// No reflection atlas. +		RID ref_texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK); +		RD::Uniform u; +		u.binding = 1; +		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; +		u.ids.push_back(ref_texture); +		uniforms.push_back(u); +	} + +	{ +		// No shadow atlas. +		RD::Uniform u; +		u.binding = 2; +		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; +		RID texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE); +		u.ids.push_back(texture); +		uniforms.push_back(u); +	} + +	{ +		// No GIProbes +		RD::Uniform u; +		u.binding = 3; +		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++) { +			u.ids.write[i] = default_tex; +		} + +		uniforms.push_back(u); +	} +	// actual sdfgi stuff + +	{ +		RD::Uniform u; +		u.uniform_type = RD::UNIFORM_TYPE_IMAGE; +		u.binding = 4; +		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.ids.push_back(p_emission_texture); +		uniforms.push_back(u); +	} +	{ +		RD::Uniform u; +		u.uniform_type = RD::UNIFORM_TYPE_IMAGE; +		u.binding = 6; +		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.ids.push_back(p_geom_facing_texture); +		uniforms.push_back(u); +	} + +	sdfgi_pass_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, RENDER_PASS_UNIFORM_SET); +	return sdfgi_pass_uniform_set; +} + +void RendererSceneRenderForward::_render_buffers_clear_uniform_set(RenderBufferDataForward *rb) { +} + +void RendererSceneRenderForward::_render_buffers_uniform_set_changed(RID p_render_buffers) { +	RenderBufferDataForward *rb = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffers); + +	_render_buffers_clear_uniform_set(rb); +} + +RID RendererSceneRenderForward::_render_buffers_get_normal_texture(RID p_render_buffers) { +	RenderBufferDataForward *rb = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffers); + +	return rb->normal_roughness_buffer; +} + +RID RendererSceneRenderForward::_render_buffers_get_ambient_texture(RID p_render_buffers) { +	RenderBufferDataForward *rb = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffers); + +	return rb->ambient_buffer; +} + +RID RendererSceneRenderForward::_render_buffers_get_reflection_texture(RID p_render_buffers) { +	RenderBufferDataForward *rb = (RenderBufferDataForward *)render_buffers_get_data(p_render_buffers); + +	return rb->reflection_buffer;  }  RendererSceneRenderForward *RendererSceneRenderForward::singleton = nullptr; @@ -2676,12 +2725,17 @@ void RendererSceneRenderForward::set_time(double p_time, double p_step) {  RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_storage) :  		RendererSceneRenderRD(p_storage) {  	singleton = this; +	low_end = is_low_end();  	storage = p_storage;  	/* SCENE SHADER */  	{  		String defines; +		if (low_end) { +			defines += "\n#define LOW_END_MODE \n"; +		} +  		defines += "\n#define MAX_ROUGHNESS_LOD " + itos(get_roughness_layers() - 1) + ".0\n";  		if (is_using_radiance_cubemap_array()) {  			defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n"; @@ -2721,6 +2775,16 @@ RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_stor  		shader_versions.push_back("\n#define USE_LIGHTMAP\n");  		shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n#define USE_LIGHTMAP\n");  		shader.scene_shader.initialize(shader_versions, defines); + +		if (is_low_end()) { +			//disable the high end versions +			shader.scene_shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS, false); +			shader.scene_shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE, false); +			shader.scene_shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_WITH_SDF, false); +			shader.scene_shader.set_variant_enabled(SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI, false); +			shader.scene_shader.set_variant_enabled(SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR, false); +			shader.scene_shader.set_variant_enabled(SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR, false); +		}  	}  	storage->shader_set_data_request_function(RendererStorageRD::SHADER_TYPE_3D, _create_shader_funcs); @@ -2924,7 +2988,9 @@ RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_stor  		MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RendererStorageRD::SHADER_TYPE_3D);  		default_shader_rd = shader.scene_shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS); -		default_shader_sdfgi_rd = shader.scene_shader.version_get_shader(md->shader_data->version, SHADER_VERSION_DEPTH_PASS_WITH_SDF); +		if (!low_end) { +			default_shader_sdfgi_rd = shader.scene_shader.version_get_shader(md->shader_data->version, SHADER_VERSION_DEPTH_PASS_WITH_SDF); +		}  	}  	{ @@ -2958,74 +3024,20 @@ RendererSceneRenderForward::RendererSceneRenderForward(RendererStorageRD *p_stor  		sampler.compare_op = RD::COMPARE_OP_LESS;  		shadow_sampler = RD::get_singleton()->sampler_create(sampler);  	} - -	{ -		Vector<RD::Uniform> uniforms; - -		RD::Uniform u; -		u.binding = 0; -		u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; -		RID texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); -		u.ids.push_back(texture); -		uniforms.push_back(u); - -		default_radiance_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, RADIANCE_UNIFORM_SET); -	} - -	{ //render buffers -		Vector<RD::Uniform> uniforms; -		for (int i = 0; i < 7; i++) { -			RD::Uniform u; -			u.binding = i; -			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; -			RID texture = storage->texture_rd_get_default(i == 0 ? RendererStorageRD::DEFAULT_RD_TEXTURE_WHITE : (i == 2 ? RendererStorageRD::DEFAULT_RD_TEXTURE_NORMAL : RendererStorageRD::DEFAULT_RD_TEXTURE_BLACK)); -			u.ids.push_back(texture); -			uniforms.push_back(u); -		} -		{ -			RD::Uniform u; -			u.binding = 7; -			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; -			RID texture = storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE); -			u.ids.push_back(texture); -			uniforms.push_back(u); -		} -		{ -			RD::Uniform u; -			u.binding = 8; -			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; -			u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); -			uniforms.push_back(u); -		} -		{ -			RD::Uniform u; -			u.binding = 9; -			u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; -			u.ids.push_back(render_buffers_get_default_gi_probe_buffer()); -			uniforms.push_back(u); -		} -		{ -			RD::Uniform u; -			u.binding = 10; -			u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; -			u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE)); -			uniforms.push_back(u); -		} - -		default_render_buffers_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, RENDER_BUFFERS_UNIFORM_SET); -	}  }  RendererSceneRenderForward::~RendererSceneRenderForward() {  	directional_shadow_atlas_set_size(0);  	//clear base uniform set if still valid -	if (view_dependant_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(view_dependant_uniform_set)) { -		RD::get_singleton()->free(view_dependant_uniform_set); +	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); +	} + +	if (sdfgi_pass_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sdfgi_pass_uniform_set)) { +		RD::get_singleton()->free(sdfgi_pass_uniform_set);  	} -	RD::get_singleton()->free(default_render_buffers_uniform_set); -	RD::get_singleton()->free(default_radiance_uniform_set);  	RD::get_singleton()->free(default_vec4_xform_buffer);  	RD::get_singleton()->free(shadow_sampler); diff --git a/servers/rendering/renderer_rd/renderer_scene_render_forward.h b/servers/rendering/renderer_rd/renderer_scene_render_forward.h index 7cea44cd38..6d76d5f0eb 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_forward.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_forward.h @@ -34,16 +34,14 @@  #include "servers/rendering/renderer_rd/pipeline_cache_rd.h"  #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"  #include "servers/rendering/renderer_rd/renderer_storage_rd.h" -#include "servers/rendering/renderer_rd/shaders/scene_high_end.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/scene_forward.glsl.gen.h"  class RendererSceneRenderForward : public RendererSceneRenderRD {  	enum {  		SCENE_UNIFORM_SET = 0, -		RADIANCE_UNIFORM_SET = 1, -		VIEW_DEPENDANT_UNIFORM_SET = 2, -		RENDER_BUFFERS_UNIFORM_SET = 3, -		TRANSFORMS_UNIFORM_SET = 4, -		MATERIAL_UNIFORM_SET = 5 +		RENDER_PASS_UNIFORM_SET = 1, +		TRANSFORMS_UNIFORM_SET = 2, +		MATERIAL_UNIFORM_SET = 3  	};  	enum { @@ -69,7 +67,7 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {  	};  	struct { -		SceneHighEndShaderRD scene_shader; +		SceneForwardShaderRD scene_shader;  		ShaderCompilerRD compiler;  	} shader; @@ -209,7 +207,7 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {  	/* Framebuffer */ -	struct RenderBufferDataHighEnd : public RenderBufferData { +	struct RenderBufferDataForward : public RenderBufferData {  		//for rendering, may be MSAAd  		RID color; @@ -246,30 +244,29 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {  		void clear();  		virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa); -		RID uniform_set; - -		~RenderBufferDataHighEnd(); +		~RenderBufferDataForward();  	};  	virtual RenderBufferData *_create_render_buffer_data(); -	void _allocate_normal_roughness_texture(RenderBufferDataHighEnd *rb); +	void _allocate_normal_roughness_texture(RenderBufferDataForward *rb);  	RID shadow_sampler;  	RID render_base_uniform_set; -	RID view_dependant_uniform_set; +	RID render_pass_uniform_set; +	RID sdfgi_pass_uniform_set;  	uint64_t lightmap_texture_array_version = 0xFFFFFFFF;  	virtual void _base_uniforms_changed(); -	void _render_buffers_clear_uniform_set(RenderBufferDataHighEnd *rb); +	void _render_buffers_clear_uniform_set(RenderBufferDataForward *rb);  	virtual void _render_buffers_uniform_set_changed(RID p_render_buffers);  	virtual RID _render_buffers_get_normal_texture(RID p_render_buffers);  	virtual RID _render_buffers_get_ambient_texture(RID p_render_buffers);  	virtual RID _render_buffers_get_reflection_texture(RID p_render_buffers);  	void _update_render_base_uniform_set(); -	void _setup_view_dependant_uniform_set(RID p_shadow_atlas, RID p_reflection_atlas, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count); -	void _update_render_buffers_uniform_set(RID p_render_buffers); +	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, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count);  	struct LightmapData {  		float normal_xform[12]; @@ -552,8 +549,6 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {  	RID wireframe_material;  	RID default_shader_rd;  	RID default_shader_sdfgi_rd; -	RID default_radiance_uniform_set; -	RID default_render_buffers_uniform_set;  	RID default_vec4_xform_buffer;  	RID default_vec4_xform_uniform_set; @@ -575,7 +570,7 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {  	void _setup_lightmaps(InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, 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_radiance_uniform_set, RID p_render_buffers_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2()); +	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());  	_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); @@ -583,6 +578,8 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {  	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, InstanceBase **p_cull_result, int p_cull_count, int p_directional_light_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, InstanceBase **p_lightmap_cull_result, int p_lightmap_cull_count, 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);  	virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, 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); diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 13fc61eee6..ee4da1b5ee 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -2971,6 +2971,10 @@ void RendererSceneRenderRD::environment_set_sdfgi(RID p_env, bool p_enable, RS::  	Environment *env = environment_owner.getornull(p_env);  	ERR_FAIL_COND(!env); +	if (low_end) { +		return; +	} +  	env->sdfgi_enabled = p_enable;  	env->sdfgi_cascades = p_cascades;  	env->sdfgi_min_cell_size = p_min_cell_size; @@ -3045,6 +3049,10 @@ void RendererSceneRenderRD::environment_set_volumetric_fog(RID p_env, bool p_ena  	Environment *env = environment_owner.getornull(p_env);  	ERR_FAIL_COND(!env); +	if (low_end) { +		return; +	} +  	env->volumetric_fog_enabled = p_enable;  	env->volumetric_fog_density = p_density;  	env->volumetric_fog_light = p_light; @@ -3095,6 +3103,10 @@ void RendererSceneRenderRD::environment_set_ssr(RID p_env, bool p_enable, int p_  	Environment *env = environment_owner.getornull(p_env);  	ERR_FAIL_COND(!env); +	if (low_end) { +		return; +	} +  	env->ssr_enabled = p_enable;  	env->ssr_max_steps = p_max_steps;  	env->ssr_fade_in = p_fade_int; @@ -3114,6 +3126,10 @@ void RendererSceneRenderRD::environment_set_ssao(RID p_env, bool p_enable, float  	Environment *env = environment_owner.getornull(p_env);  	ERR_FAIL_COND(!env); +	if (low_end) { +		return; +	} +  	env->ssao_enabled = p_enable;  	env->ssao_radius = p_radius;  	env->ssao_intensity = p_intensity; @@ -4024,6 +4040,10 @@ bool RendererSceneRenderRD::gi_probe_needs_update(RID p_probe) const {  	GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);  	ERR_FAIL_COND_V(!gi_probe, false); +	if (low_end) { +		return false; +	} +  	//return true;  	return gi_probe->last_probe_version != storage->gi_probe_get_version(gi_probe->probe);  } @@ -4032,6 +4052,10 @@ void RendererSceneRenderRD::gi_probe_update(RID p_probe, bool p_update_light_ins  	GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe);  	ERR_FAIL_COND(!gi_probe); +	if (low_end) { +		return; +	} +  	uint32_t data_version = storage->gi_probe_get_data_version(gi_probe->probe);  	// (RE)CREATE IF NEEDED @@ -7952,6 +7976,10 @@ int RendererSceneRenderRD::get_max_directional_lights() const {  	return cluster.max_directional_lights;  } +bool RendererSceneRenderRD::is_low_end() const { +	return low_end; +} +  RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {  	storage = p_storage;  	singleton = this; @@ -7961,9 +7989,15 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {  	sky_use_cubemap_array = GLOBAL_GET("rendering/quality/reflections/texture_array_reflections");  	//	sky_use_cubemap_array = false; -	//uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE); +	uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE); -	{ +	low_end = GLOBAL_GET("rendering/quality/rd_renderer/use_low_end_renderer"); + +	if (textures_per_stage < 48) { +		low_end = true; +	} + +	if (!low_end) {  		//kinda complicated to compute the amount of slots, we try to use as many as we can  		gi_probe_max_lights = 32; @@ -7992,7 +8026,7 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {  		}  	} -	{ +	if (!low_end) {  		String defines;  		Vector<String> versions;  		versions.push_back("\n#define MODE_DEBUG_COLOR\n"); @@ -8208,121 +8242,125 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {  		sky_scene_state.fog_only_texture_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_TEXTURES);  	} -	{ -		Vector<String> preprocess_modes; -		preprocess_modes.push_back("\n#define MODE_SCROLL\n"); -		preprocess_modes.push_back("\n#define MODE_SCROLL_OCCLUSION\n"); -		preprocess_modes.push_back("\n#define MODE_INITIALIZE_JUMP_FLOOD\n"); -		preprocess_modes.push_back("\n#define MODE_INITIALIZE_JUMP_FLOOD_HALF\n"); -		preprocess_modes.push_back("\n#define MODE_JUMPFLOOD\n"); -		preprocess_modes.push_back("\n#define MODE_JUMPFLOOD_OPTIMIZED\n"); -		preprocess_modes.push_back("\n#define MODE_UPSCALE_JUMP_FLOOD\n"); -		preprocess_modes.push_back("\n#define MODE_OCCLUSION\n"); -		preprocess_modes.push_back("\n#define MODE_STORE\n"); -		String defines = "\n#define OCCLUSION_SIZE " + itos(SDFGI::CASCADE_SIZE / SDFGI::PROBE_DIVISOR) + "\n"; -		sdfgi_shader.preprocess.initialize(preprocess_modes, defines); -		sdfgi_shader.preprocess_shader = sdfgi_shader.preprocess.version_create(); -		for (int i = 0; i < SDGIShader::PRE_PROCESS_MAX; i++) { -			sdfgi_shader.preprocess_pipeline[i] = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, i)); +	if (!low_end) { +		//SDFGI +		{ +			Vector<String> preprocess_modes; +			preprocess_modes.push_back("\n#define MODE_SCROLL\n"); +			preprocess_modes.push_back("\n#define MODE_SCROLL_OCCLUSION\n"); +			preprocess_modes.push_back("\n#define MODE_INITIALIZE_JUMP_FLOOD\n"); +			preprocess_modes.push_back("\n#define MODE_INITIALIZE_JUMP_FLOOD_HALF\n"); +			preprocess_modes.push_back("\n#define MODE_JUMPFLOOD\n"); +			preprocess_modes.push_back("\n#define MODE_JUMPFLOOD_OPTIMIZED\n"); +			preprocess_modes.push_back("\n#define MODE_UPSCALE_JUMP_FLOOD\n"); +			preprocess_modes.push_back("\n#define MODE_OCCLUSION\n"); +			preprocess_modes.push_back("\n#define MODE_STORE\n"); +			String defines = "\n#define OCCLUSION_SIZE " + itos(SDFGI::CASCADE_SIZE / SDFGI::PROBE_DIVISOR) + "\n"; +			sdfgi_shader.preprocess.initialize(preprocess_modes, defines); +			sdfgi_shader.preprocess_shader = sdfgi_shader.preprocess.version_create(); +			for (int i = 0; i < SDGIShader::PRE_PROCESS_MAX; i++) { +				sdfgi_shader.preprocess_pipeline[i] = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.preprocess.version_get_shader(sdfgi_shader.preprocess_shader, i)); +			}  		} -	} -	{ -		//calculate tables -		String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; +		{ +			//calculate tables +			String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; -		Vector<String> direct_light_modes; -		direct_light_modes.push_back("\n#define MODE_PROCESS_STATIC\n"); -		direct_light_modes.push_back("\n#define MODE_PROCESS_DYNAMIC\n"); -		sdfgi_shader.direct_light.initialize(direct_light_modes, defines); -		sdfgi_shader.direct_light_shader = sdfgi_shader.direct_light.version_create(); -		for (int i = 0; i < SDGIShader::DIRECT_LIGHT_MODE_MAX; i++) { -			sdfgi_shader.direct_light_pipeline[i] = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.direct_light.version_get_shader(sdfgi_shader.direct_light_shader, i)); +			Vector<String> direct_light_modes; +			direct_light_modes.push_back("\n#define MODE_PROCESS_STATIC\n"); +			direct_light_modes.push_back("\n#define MODE_PROCESS_DYNAMIC\n"); +			sdfgi_shader.direct_light.initialize(direct_light_modes, defines); +			sdfgi_shader.direct_light_shader = sdfgi_shader.direct_light.version_create(); +			for (int i = 0; i < SDGIShader::DIRECT_LIGHT_MODE_MAX; i++) { +				sdfgi_shader.direct_light_pipeline[i] = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.direct_light.version_get_shader(sdfgi_shader.direct_light_shader, i)); +			}  		} -	} -	{ -		//calculate tables -		String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; -		defines += "\n#define SH_SIZE " + itos(SDFGI::SH_SIZE) + "\n"; - -		Vector<String> integrate_modes; -		integrate_modes.push_back("\n#define MODE_PROCESS\n"); -		integrate_modes.push_back("\n#define MODE_STORE\n"); -		integrate_modes.push_back("\n#define MODE_SCROLL\n"); -		integrate_modes.push_back("\n#define MODE_SCROLL_STORE\n"); -		sdfgi_shader.integrate.initialize(integrate_modes, defines); -		sdfgi_shader.integrate_shader = sdfgi_shader.integrate.version_create(); +		{ +			//calculate tables +			String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; +			defines += "\n#define SH_SIZE " + itos(SDFGI::SH_SIZE) + "\n"; -		for (int i = 0; i < SDGIShader::INTEGRATE_MODE_MAX; i++) { -			sdfgi_shader.integrate_pipeline[i] = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.integrate.version_get_shader(sdfgi_shader.integrate_shader, i)); -		} +			Vector<String> integrate_modes; +			integrate_modes.push_back("\n#define MODE_PROCESS\n"); +			integrate_modes.push_back("\n#define MODE_STORE\n"); +			integrate_modes.push_back("\n#define MODE_SCROLL\n"); +			integrate_modes.push_back("\n#define MODE_SCROLL_STORE\n"); +			sdfgi_shader.integrate.initialize(integrate_modes, defines); +			sdfgi_shader.integrate_shader = sdfgi_shader.integrate.version_create(); -		{ -			Vector<RD::Uniform> uniforms; +			for (int i = 0; i < SDGIShader::INTEGRATE_MODE_MAX; i++) { +				sdfgi_shader.integrate_pipeline[i] = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.integrate.version_get_shader(sdfgi_shader.integrate_shader, i)); +			}  			{ -				RD::Uniform u; -				u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; -				u.binding = 0; -				u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE)); -				uniforms.push_back(u); +				Vector<RD::Uniform> uniforms; + +				{ +					RD::Uniform u; +					u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; +					u.binding = 0; +					u.ids.push_back(storage->texture_rd_get_default(RendererStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE)); +					uniforms.push_back(u); +				} +				{ +					RD::Uniform u; +					u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; +					u.binding = 1; +					u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); +					uniforms.push_back(u); +				} + +				sdfgi_shader.integrate_default_sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.integrate.version_get_shader(sdfgi_shader.integrate_shader, 0), 1);  			} -			{ -				RD::Uniform u; -				u.uniform_type = RD::UNIFORM_TYPE_SAMPLER; -				u.binding = 1; -				u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); -				uniforms.push_back(u); +		} +		{ +			//calculate tables +			String defines = "\n#define SDFGI_OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; +			Vector<String> gi_modes; +			gi_modes.push_back(""); +			gi.shader.initialize(gi_modes, defines); +			gi.shader_version = gi.shader.version_create(); +			for (int i = 0; i < GI::MODE_MAX; i++) { +				gi.pipelines[i] = RD::get_singleton()->compute_pipeline_create(gi.shader.version_get_shader(gi.shader_version, i));  			} -			sdfgi_shader.integrate_default_sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sdfgi_shader.integrate.version_get_shader(sdfgi_shader.integrate_shader, 0), 1); +			gi.sdfgi_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(GI::SDFGIData));  		} -	} -	{ -		//calculate tables -		String defines = "\n#define SDFGI_OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; -		Vector<String> gi_modes; -		gi_modes.push_back(""); -		gi.shader.initialize(gi_modes, defines); -		gi.shader_version = gi.shader.version_create(); -		for (int i = 0; i < GI::MODE_MAX; i++) { -			gi.pipelines[i] = RD::get_singleton()->compute_pipeline_create(gi.shader.version_get_shader(gi.shader_version, i)); +		{ +			String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; +			Vector<String> debug_modes; +			debug_modes.push_back(""); +			sdfgi_shader.debug.initialize(debug_modes, defines); +			sdfgi_shader.debug_shader = sdfgi_shader.debug.version_create(); +			sdfgi_shader.debug_shader_version = sdfgi_shader.debug.version_get_shader(sdfgi_shader.debug_shader, 0); +			sdfgi_shader.debug_pipeline = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.debug_shader_version);  		} +		{ +			String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; -		gi.sdfgi_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(GI::SDFGIData)); -	} -	{ -		String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; -		Vector<String> debug_modes; -		debug_modes.push_back(""); -		sdfgi_shader.debug.initialize(debug_modes, defines); -		sdfgi_shader.debug_shader = sdfgi_shader.debug.version_create(); -		sdfgi_shader.debug_shader_version = sdfgi_shader.debug.version_get_shader(sdfgi_shader.debug_shader, 0); -		sdfgi_shader.debug_pipeline = RD::get_singleton()->compute_pipeline_create(sdfgi_shader.debug_shader_version); -	} -	{ -		String defines = "\n#define OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n"; - -		Vector<String> versions; -		versions.push_back("\n#define MODE_PROBES\n"); -		versions.push_back("\n#define MODE_VISIBILITY\n"); +			Vector<String> versions; +			versions.push_back("\n#define MODE_PROBES\n"); +			versions.push_back("\n#define MODE_VISIBILITY\n"); -		sdfgi_shader.debug_probes.initialize(versions, defines); -		sdfgi_shader.debug_probes_shader = sdfgi_shader.debug_probes.version_create(); +			sdfgi_shader.debug_probes.initialize(versions, defines); +			sdfgi_shader.debug_probes_shader = sdfgi_shader.debug_probes.version_create(); -		{ -			RD::PipelineRasterizationState rs; -			rs.cull_mode = RD::POLYGON_CULL_DISABLED; -			RD::PipelineDepthStencilState ds; -			ds.enable_depth_test = true; -			ds.enable_depth_write = true; -			ds.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL; -			for (int i = 0; i < SDGIShader::PROBE_DEBUG_MAX; i++) { -				RID debug_probes_shader_version = sdfgi_shader.debug_probes.version_get_shader(sdfgi_shader.debug_probes_shader, i); -				sdfgi_shader.debug_probes_pipeline[i].setup(debug_probes_shader_version, RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0); +			{ +				RD::PipelineRasterizationState rs; +				rs.cull_mode = RD::POLYGON_CULL_DISABLED; +				RD::PipelineDepthStencilState ds; +				ds.enable_depth_test = true; +				ds.enable_depth_write = true; +				ds.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL; +				for (int i = 0; i < SDGIShader::PROBE_DEBUG_MAX; i++) { +					RID debug_probes_shader_version = sdfgi_shader.debug_probes.version_get_shader(sdfgi_shader.debug_probes_shader, i); +					sdfgi_shader.debug_probes_pipeline[i].setup(debug_probes_shader_version, RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0); +				}  			}  		} +		default_giprobe_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(GI::GIProbeData) * RenderBuffers::MAX_GIPROBES);  	}  	//cluster setup @@ -8366,7 +8404,7 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {  	cluster.builder.setup(16, 8, 24); -	{ +	if (!low_end) {  		String defines = "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(cluster.max_directional_lights) + "\n";  		Vector<String> volumetric_fog_modes;  		volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n"); @@ -8379,7 +8417,6 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {  			volumetric_fog.pipelines[i] = RD::get_singleton()->compute_pipeline_create(volumetric_fog.shader.version_get_shader(volumetric_fog.shader_version, i));  		}  	} -	default_giprobe_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(GI::GIProbeData) * RenderBuffers::MAX_GIPROBES);  	{  		RD::SamplerState sampler; @@ -8427,22 +8464,25 @@ RendererSceneRenderRD::~RendererSceneRenderRD() {  		RD::get_singleton()->free(sky_scene_state.uniform_set);  	} -	RD::get_singleton()->free(default_giprobe_buffer); -	RD::get_singleton()->free(gi_probe_lights_uniform); -	RD::get_singleton()->free(gi.sdfgi_ubo); +	if (!low_end) { +		RD::get_singleton()->free(default_giprobe_buffer); +		RD::get_singleton()->free(gi_probe_lights_uniform); +		RD::get_singleton()->free(gi.sdfgi_ubo); -	giprobe_debug_shader.version_free(giprobe_debug_shader_version); -	giprobe_shader.version_free(giprobe_lighting_shader_version); -	gi.shader.version_free(gi.shader_version); -	sdfgi_shader.debug_probes.version_free(sdfgi_shader.debug_probes_shader); -	sdfgi_shader.debug.version_free(sdfgi_shader.debug_shader); -	sdfgi_shader.direct_light.version_free(sdfgi_shader.direct_light_shader); -	sdfgi_shader.integrate.version_free(sdfgi_shader.integrate_shader); -	sdfgi_shader.preprocess.version_free(sdfgi_shader.preprocess_shader); +		giprobe_debug_shader.version_free(giprobe_debug_shader_version); +		giprobe_shader.version_free(giprobe_lighting_shader_version); +		gi.shader.version_free(gi.shader_version); +		sdfgi_shader.debug_probes.version_free(sdfgi_shader.debug_probes_shader); +		sdfgi_shader.debug.version_free(sdfgi_shader.debug_shader); +		sdfgi_shader.direct_light.version_free(sdfgi_shader.direct_light_shader); +		sdfgi_shader.integrate.version_free(sdfgi_shader.integrate_shader); +		sdfgi_shader.preprocess.version_free(sdfgi_shader.preprocess_shader); -	volumetric_fog.shader.version_free(volumetric_fog.shader_version); +		volumetric_fog.shader.version_free(volumetric_fog.shader_version); + +		memdelete_arr(gi_probe_lights); +	} -	memdelete_arr(gi_probe_lights);  	SkyMaterialData *md = (SkyMaterialData *)storage->material_get_data(sky_shader.default_material, RendererStorageRD::SHADER_TYPE_SKY);  	sky_shader.shader.version_free(md->shader_data->version);  	RD::get_singleton()->free(sky_scene_state.directional_light_buffer); diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index 8c994849c3..e3dfee2da7 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -1456,6 +1456,8 @@ private:  		float weight;  	}; +	bool low_end = false; +  public:  	/* SHADOW ATLAS API */ @@ -1952,6 +1954,8 @@ public:  	void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir); +	bool is_low_end() const; +  	RendererSceneRenderRD(RendererStorageRD *p_storage);  	~RendererSceneRenderRD();  }; diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp index bf7ec54b9c..41126218ae 100644 --- a/servers/rendering/renderer_rd/shader_rd.cpp +++ b/servers/rendering/renderer_rd/shader_rd.cpp @@ -199,6 +199,10 @@ void ShaderRD::_clear_version(Version *p_version) {  }  void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) { +	if (!variants_enabled[p_variant]) { +		return; //variant is disabled, return +	} +  	Vector<RD::ShaderStageData> stages;  	String error; @@ -365,6 +369,9 @@ void ShaderRD::_compile_version(Version *p_version) {  	bool all_valid = true;  	for (int i = 0; i < variant_defines.size(); i++) { +		if (!variants_enabled[i]) { +			continue; //disabled +		}  		if (p_version->variants[i].is_null()) {  			all_valid = false;  			break; @@ -374,6 +381,9 @@ void ShaderRD::_compile_version(Version *p_version) {  	if (!all_valid) {  		//clear versions if they exist  		for (int i = 0; i < variant_defines.size(); i++) { +			if (!variants_enabled[i]) { +				continue; //disabled +			}  			if (!p_version->variants[i].is_null()) {  				RD::get_singleton()->free(p_version->variants[i]);  			} @@ -454,12 +464,26 @@ bool ShaderRD::version_free(RID p_version) {  	return true;  } +void ShaderRD::set_variant_enabled(int p_variant, bool p_enabled) { +	ERR_FAIL_COND(version_owner.get_rid_count() > 0); //versions exist +	ERR_FAIL_INDEX(p_variant, variants_enabled.size()); +	variants_enabled.write[p_variant] = p_enabled; +} + +bool ShaderRD::is_variant_enabled(int p_variant) const { +	ERR_FAIL_INDEX_V(p_variant, variants_enabled.size(), false); +	return variants_enabled[p_variant]; +} +  void ShaderRD::initialize(const Vector<String> &p_variant_defines, const String &p_general_defines) {  	ERR_FAIL_COND(variant_defines.size());  	ERR_FAIL_COND(p_variant_defines.size() == 0); +  	general_defines = p_general_defines.utf8(); +  	for (int i = 0; i < p_variant_defines.size(); i++) {  		variant_defines.push_back(p_variant_defines[i].utf8()); +		variants_enabled.push_back(true);  	}  } diff --git a/servers/rendering/renderer_rd/shader_rd.h b/servers/rendering/renderer_rd/shader_rd.h index 0c379db6f2..05e07d3cf3 100644 --- a/servers/rendering/renderer_rd/shader_rd.h +++ b/servers/rendering/renderer_rd/shader_rd.h @@ -46,6 +46,7 @@ class ShaderRD {  	//versions  	CharString general_defines;  	Vector<CharString> variant_defines; +	Vector<bool> variants_enabled;  	struct Version {  		CharString uniforms; @@ -109,6 +110,7 @@ public:  	_FORCE_INLINE_ RID version_get_shader(RID p_version, int p_variant) {  		ERR_FAIL_INDEX_V(p_variant, variant_defines.size(), RID()); +		ERR_FAIL_COND_V(!variants_enabled[p_variant], RID());  		Version *version = version_owner.getornull(p_version);  		ERR_FAIL_COND_V(!version, RID()); @@ -128,6 +130,9 @@ public:  	bool version_free(RID p_version); +	void set_variant_enabled(int p_variant, bool p_enabled); +	bool is_variant_enabled(int p_variant) const; +  	void initialize(const Vector<String> &p_variant_defines, const String &p_general_defines = "");  	virtual ~ShaderRD();  }; diff --git a/servers/rendering/renderer_rd/shaders/SCsub b/servers/rendering/renderer_rd/shaders/SCsub index 4cddf0f685..1fe43b25f6 100644 --- a/servers/rendering/renderer_rd/shaders/SCsub +++ b/servers/rendering/renderer_rd/shaders/SCsub @@ -11,7 +11,7 @@ if "RD_GLSL" in env["BUILDERS"]:      env.RD_GLSL("cubemap_roughness.glsl")      env.RD_GLSL("cubemap_downsampler.glsl")      env.RD_GLSL("cubemap_filter.glsl") -    env.RD_GLSL("scene_high_end.glsl") +    env.RD_GLSL("scene_forward.glsl")      env.RD_GLSL("sky.glsl")      env.RD_GLSL("tonemap.glsl")      env.RD_GLSL("cube_to_dp.glsl") diff --git a/servers/rendering/renderer_rd/shaders/scene_high_end.glsl b/servers/rendering/renderer_rd/shaders/scene_forward.glsl index 5d87dec79f..5b01cb1f82 100644 --- a/servers/rendering/renderer_rd/shaders/scene_high_end.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward.glsl @@ -4,7 +4,7 @@  VERSION_DEFINES -#include "scene_high_end_inc.glsl" +#include "scene_forward_inc.glsl"  /* INPUT ATTRIBS */ @@ -296,7 +296,7 @@ VERTEX_SHADER_CODE  VERSION_DEFINES -#include "scene_high_end_inc.glsl" +#include "scene_forward_inc.glsl"  /* Varyings */ @@ -1548,8 +1548,6 @@ void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3  	out_spec += vec4(irr_light.rgb * blend, blend);  } -#endif //USE_FORWARD_GI -  vec2 octahedron_wrap(vec2 v) {  	vec2 signVal;  	signVal.x = v.x >= 0.0 ? 1.0 : -1.0; @@ -1683,10 +1681,14 @@ void sdfgi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_normal  	}  } +#endif //USE_FORWARD_GI +  #endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)  #ifndef MODE_RENDER_DEPTH +#ifndef LOW_END_MODE +  vec4 volumetric_fog_process(vec2 screen_uv, float z) {  	vec3 fog_pos = vec3(screen_uv, z * scene_data.volumetric_fog_inv_length);  	if (fog_pos.z < 0.0) { @@ -1697,6 +1699,7 @@ vec4 volumetric_fog_process(vec2 screen_uv, float z) {  	return texture(sampler3D(volumetric_fog_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), fog_pos);  } +#endif  vec4 fog_process(vec3 vertex) {  	vec3 fog_color = scene_data.fog_light_color; @@ -2221,30 +2224,13 @@ FRAGMENT_SHADER_CODE  		specular_light = spec_accum.rgb;  		ambient_light = amb_accum.rgb;  	} -#else +#elif !defined(LOW_END_MODE) +  	if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GI_BUFFERS)) { //use GI buffers  		ivec2 coord;  		if (scene_data.gi_upscale_for_msaa) { -			/* -			//find the closest depth to upscale from, based on neighbours -			ivec2 base_coord = ivec2(gl_FragCoord.xy); -			float z_dist = gl_FragCoord.z; -			ivec2 closest_coord = base_coord; -			float closest_z_dist = abs(texelFetch(sampler2D(depth_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), base_coord,0).r-z_dist); - -			for(int i=0;i<4;i++) { -				const ivec2 neighbours[4]=ivec2[](ivec2(-1,0),ivec2(1,0),ivec2(0,-1),ivec2(0,1)); -				ivec2 neighbour_coord = base_coord + neighbours[i]; -				float neighbour_z_dist = abs(texelFetch(sampler2D(depth_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), neighbour_coord,0).r-z_dist); -				if (neighbour_z_dist < closest_z_dist) { -					closest_z_dist = neighbour_z_dist; -					closest_coord = neighbour_coord; -				} -			} - -*/  			ivec2 base_coord = ivec2(gl_FragCoord.xy);  			ivec2 closest_coord = base_coord;  			float closest_ang = dot(normal, texelFetch(sampler2D(normal_roughness_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), base_coord, 0).xyz * 2.0 - 1.0); @@ -2823,11 +2809,13 @@ FRAGMENT_SHADER_CODE  //ambient occlusion  #if defined(AO_USED) +#ifndef LOW_END_MODE  	if (scene_data.ssao_enabled && scene_data.ssao_ao_affect > 0.0) {  		float ssao = texture(sampler2D(ao_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv).r;  		ao = mix(ao, min(ao, ssao), scene_data.ssao_ao_affect);  		ao_light_affect = mix(ao_light_affect, max(ao_light_affect, scene_data.ssao_light_affect), scene_data.ssao_ao_affect);  	} +#endif //LOW_END_MODE  	ambient_light = mix(scene_data.ao_color.rgb, ambient_light, ao);  	ao_light_affect = mix(1.0, ao, ao_light_affect); @@ -2835,6 +2823,7 @@ FRAGMENT_SHADER_CODE  	diffuse_light = mix(scene_data.ao_color.rgb, diffuse_light, ao_light_affect);  #else +#ifndef LOW_END_MODE  	if (scene_data.ssao_enabled) {  		float ao = texture(sampler2D(ao_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv).r;  		ambient_light = mix(scene_data.ao_color.rgb, ambient_light, ao); @@ -2842,6 +2831,7 @@ FRAGMENT_SHADER_CODE  		specular_light = mix(scene_data.ao_color.rgb, specular_light, ao_light_affect);  		diffuse_light = mix(scene_data.ao_color.rgb, diffuse_light, ao_light_affect);  	} +#endif //LOW_END_MODE  #endif // AO_USED @@ -2871,11 +2861,13 @@ FRAGMENT_SHADER_CODE  		specular_buffer.rgb = mix(specular_buffer.rgb, vec3(0.0), fog.a);  	} +#ifndef LOW_END_MODE  	if (scene_data.volumetric_fog_enabled) {  		vec4 fog = volumetric_fog_process(screen_uv, -vertex.z);  		diffuse_buffer.rgb = mix(diffuse_buffer.rgb, fog.rgb, fog.a);  		specular_buffer.rgb = mix(specular_buffer.rgb, vec3(0.0), fog.a);  	} +#endif // LOW_END_MODE  #if defined(CUSTOM_FOG_USED)  	diffuse_buffer.rgb = mix(diffuse_buffer.rgb, custom_fog.rgb, custom_fog.a); @@ -2896,11 +2888,12 @@ FRAGMENT_SHADER_CODE  		vec4 fog = fog_process(vertex);  		frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a);  	} - +#ifndef LOW_END_MODE  	if (scene_data.volumetric_fog_enabled) {  		vec4 fog = volumetric_fog_process(screen_uv, -vertex.z);  		frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a);  	} +#endif  #if defined(CUSTOM_FOG_USED)  	frag_color.rgb = mix(frag_color.rgb, custom_fog.rgb, custom_fog.a); diff --git a/servers/rendering/renderer_rd/shaders/scene_high_end_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_inc.glsl index e29a490ca1..d18581c1b3 100644 --- a/servers/rendering/renderer_rd/shaders/scene_high_end_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_inc.glsl @@ -204,6 +204,8 @@ layout(set = 0, binding = 19, std430) restrict readonly buffer GlobalVariableDat  }  global_variables; +#ifndef LOW_END_MODE +  struct SDFGIProbeCascadeData {  	vec3 position;  	float to_probe; @@ -239,6 +241,8 @@ layout(set = 0, binding = 20, std140) uniform SDFGI {  }  sdfgi; +#endif //LOW_END_MODE +  // decal atlas  /* Set 1, Radiance */ @@ -255,20 +259,22 @@ layout(set = 1, binding = 0) uniform textureCube radiance_cubemap;  /* Set 2, Reflection and Shadow Atlases (view dependent) */ -layout(set = 2, binding = 0) uniform textureCubeArray reflection_atlas; +layout(set = 1, binding = 1) uniform textureCubeArray reflection_atlas; -layout(set = 2, binding = 1) uniform texture2D shadow_atlas; +layout(set = 1, binding = 2) uniform texture2D shadow_atlas; -layout(set = 2, binding = 2) uniform texture3D gi_probe_textures[MAX_GI_PROBES]; +#ifndef LOW_END_MODE +layout(set = 1, binding = 3) uniform texture3D gi_probe_textures[MAX_GI_PROBES]; +#endif  /* Set 3, Render Buffers */  #ifdef MODE_RENDER_SDF -layout(r16ui, set = 3, binding = 0) uniform restrict writeonly uimage3D albedo_volume_grid; -layout(r32ui, set = 3, binding = 1) uniform restrict writeonly uimage3D emission_grid; -layout(r32ui, set = 3, binding = 2) uniform restrict writeonly uimage3D emission_aniso_grid; -layout(r32ui, set = 3, binding = 3) uniform restrict uimage3D geom_facing_grid; +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;  //still need to be present for shaders that use it, so remap them to something  #define depth_buffer shadow_atlas @@ -277,14 +283,17 @@ layout(r32ui, set = 3, binding = 3) uniform restrict uimage3D geom_facing_grid;  #else -layout(set = 3, binding = 0) uniform texture2D depth_buffer; -layout(set = 3, binding = 1) uniform texture2D color_buffer; -layout(set = 3, binding = 2) uniform texture2D normal_roughness_buffer; -layout(set = 3, binding = 4) uniform texture2D ao_buffer; -layout(set = 3, binding = 5) uniform texture2D ambient_buffer; -layout(set = 3, binding = 6) uniform texture2D reflection_buffer; -layout(set = 3, binding = 7) uniform texture2DArray sdfgi_lightprobe_texture; -layout(set = 3, binding = 8) uniform texture3D sdfgi_occlusion_cascades; +layout(set = 1, binding = 4) uniform texture2D depth_buffer; +layout(set = 1, binding = 5) 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;  struct GIProbeData {  	mat4 xform; @@ -302,18 +311,20 @@ struct GIProbeData {  	uint mipmaps;  }; -layout(set = 3, binding = 9, std140) uniform GIProbes { +layout(set = 1, binding = 12, std140) uniform GIProbes {  	GIProbeData data[MAX_GI_PROBES];  }  gi_probes; -layout(set = 3, binding = 10) uniform texture3D volumetric_fog_texture; +layout(set = 1, binding = 13) uniform texture3D volumetric_fog_texture; + +#endif // LOW_END_MODE  #endif  /* Set 4 Skeleton & Instancing (Multimesh) */ -layout(set = 4, binding = 0, std430) restrict readonly buffer Transforms { +layout(set = 2, binding = 0, std430) restrict readonly buffer Transforms {  	vec4 data[];  }  transforms;  |