Jelajahi Sumber

Shader optimizations to reduce VGPR usage and increase occupancy

reduz 4 tahun lalu
induk
melakukan
7008e3c6ea

+ 16 - 26
servers/rendering/renderer_rd/renderer_scene_render_rd.cpp

@@ -6062,22 +6062,17 @@ void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflecti
 		reflection_ubo.box_offset[2] = origin_offset.z;
 		reflection_ubo.mask = storage->reflection_probe_get_cull_mask(base_probe);
 
-		float intensity = storage->reflection_probe_get_intensity(base_probe);
-		bool interior = storage->reflection_probe_is_interior(base_probe);
-		bool box_projection = storage->reflection_probe_is_box_projection(base_probe);
+		reflection_ubo.intensity = storage->reflection_probe_get_intensity(base_probe);
+		reflection_ubo.ambient_mode = storage->reflection_probe_get_ambient_mode(base_probe);
 
-		reflection_ubo.params[0] = intensity;
-		reflection_ubo.params[1] = 0;
-		reflection_ubo.params[2] = interior ? 1.0 : 0.0;
-		reflection_ubo.params[3] = box_projection ? 1.0 : 0.0;
+		reflection_ubo.exterior = !storage->reflection_probe_is_interior(base_probe);
+		reflection_ubo.box_project = storage->reflection_probe_is_box_projection(base_probe);
 
 		Color ambient_linear = storage->reflection_probe_get_ambient_color(base_probe).to_linear();
 		float interior_ambient_energy = storage->reflection_probe_get_ambient_color_energy(base_probe);
-		uint32_t ambient_mode = storage->reflection_probe_get_ambient_mode(base_probe);
 		reflection_ubo.ambient[0] = ambient_linear.r * interior_ambient_energy;
 		reflection_ubo.ambient[1] = ambient_linear.g * interior_ambient_energy;
 		reflection_ubo.ambient[2] = ambient_linear.b * interior_ambient_energy;
-		reflection_ubo.ambient_mode = ambient_mode;
 
 		Transform transform = reflection_probe_instance_get_transform(rpi);
 		Transform proj = (p_camera_inverse_transform * transform).inverse();
@@ -6300,13 +6295,14 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
 				float sign = storage->light_is_negative(base) ? -1 : 1;
 				Color linear_col = storage->light_get_color(base).to_linear();
 
-				light_data.attenuation_energy[0] = Math::make_half_float(storage->light_get_param(base, RS::LIGHT_PARAM_ATTENUATION));
-				light_data.attenuation_energy[1] = Math::make_half_float(sign * storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI);
+				light_data.attenuation = storage->light_get_param(base, RS::LIGHT_PARAM_ATTENUATION);
 
-				light_data.color_specular[0] = MIN(uint32_t(linear_col.r * 255), 255);
-				light_data.color_specular[1] = MIN(uint32_t(linear_col.g * 255), 255);
-				light_data.color_specular[2] = MIN(uint32_t(linear_col.b * 255), 255);
-				light_data.color_specular[3] = MIN(uint32_t(storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR) * 255), 255);
+				float energy = sign * storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI;
+
+				light_data.color[0] = linear_col.r * energy;
+				light_data.color[1] = linear_col.g * energy;
+				light_data.color[2] = linear_col.b * energy;
+				light_data.specular_amount = storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR);
 
 				float radius = MAX(0.001, storage->light_get_param(base, RS::LIGHT_PARAM_RANGE));
 				light_data.inv_radius = 1.0 / radius;
@@ -6327,9 +6323,9 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
 
 				light_data.size = size;
 
-				light_data.cone_attenuation_angle[0] = Math::make_half_float(storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ATTENUATION));
+				light_data.cone_attenuation = storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
 				float spot_angle = storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ANGLE);
-				light_data.cone_attenuation_angle[1] = Math::make_half_float(Math::cos(Math::deg2rad(spot_angle)));
+				light_data.cone_angle = Math::cos(Math::deg2rad(spot_angle));
 
 				light_data.mask = storage->light_get_cull_mask(base);
 
@@ -6364,12 +6360,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
 				if (p_using_shadows && p_shadow_atlas.is_valid() && shadow_atlas_owns_light_instance(p_shadow_atlas, li)) {
 					// fill in the shadow information
 
-					Color shadow_color = storage->light_get_shadow_color(base);
-
-					light_data.shadow_color_enabled[0] = MIN(uint32_t(shadow_color.r * 255), 255);
-					light_data.shadow_color_enabled[1] = MIN(uint32_t(shadow_color.g * 255), 255);
-					light_data.shadow_color_enabled[2] = MIN(uint32_t(shadow_color.b * 255), 255);
-					light_data.shadow_color_enabled[3] = 255;
+					light_data.shadow_enabled = true;
 
 					if (type == RS::LIGHT_SPOT) {
 						light_data.shadow_bias = (storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) * radius / 10.0);
@@ -6427,7 +6418,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
 						}
 					}
 				} else {
-					light_data.shadow_color_enabled[3] = 0;
+					light_data.shadow_enabled = false;
 				}
 
 				light_instance_set_index(li, light_count);
@@ -6763,7 +6754,7 @@ void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_e
 		cluster.lights_shadow_rect_cache_count = 0;
 
 		for (int i = 0; i < p_positional_light_count; i++) {
-			if (cluster.lights[i].shadow_color_enabled[3] > 127) {
+			if (cluster.lights[i].shadow_enabled != 0) {
 				RID li = cluster.lights_instances[i];
 
 				ERR_CONTINUE(!shadow_atlas->shadow_owners.has(li));
@@ -8499,7 +8490,6 @@ RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {
 	{ //reflections
 		uint32_t reflection_buffer_size;
 		if (uniform_max_size < 65536) {
-			//Yes, you guessed right, ARM again
 			reflection_buffer_size = uniform_max_size;
 		} else {
 			reflection_buffer_size = 65536;

+ 20 - 6
servers/rendering/renderer_rd/renderer_scene_render_rd.h

@@ -1297,14 +1297,23 @@ private:
 	struct Cluster {
 		/* Scene State UBO */
 
-		struct ReflectionData { //should always be 128 bytes
+		enum {
+			REFLECTION_AMBIENT_DISABLED = 0,
+			REFLECTION_AMBIENT_ENVIRONMENT = 1,
+			REFLECTION_AMBIENT_COLOR = 2,
+		};
+
+		struct ReflectionData {
 			float box_extents[3];
 			float index;
 			float box_offset[3];
 			uint32_t mask;
-			float params[4]; // intensity, 0, interior , boxproject
 			float ambient[3]; // ambient color,
+			float intensity;
+			bool exterior;
+			bool box_project;
 			uint32_t ambient_mode;
+			uint32_t pad;
 			float local_matrix[16]; // up to here for spot and omni, rest is for directional
 		};
 
@@ -1313,10 +1322,15 @@ private:
 			float inv_radius;
 			float direction[3];
 			float size;
-			uint16_t attenuation_energy[2]; //16 bits attenuation, then energy
-			uint8_t color_specular[4]; //rgb color, a specular (8 bit unorm)
-			uint16_t cone_attenuation_angle[2]; // attenuation and angle, (16bit float)
-			uint8_t shadow_color_enabled[4]; //shadow rgb color, a>0.5 enabled (8bit unorm)
+
+			float color[3];
+			float attenuation;
+
+			float cone_attenuation;
+			float cone_angle;
+			float specular_amount;
+			uint32_t shadow_enabled;
+
 			float atlas_rect[4]; // in omni, used for atlas uv, in spot, used for projector uv
 			float shadow_matrix[16];
 			float shadow_bias;

+ 15 - 5
servers/rendering/renderer_rd/shaders/cluster_data_inc.glsl

@@ -6,12 +6,18 @@
 struct LightData { //this structure needs to be as packed as possible
 	vec3 position;
 	float inv_radius;
+
 	vec3 direction;
 	float size;
-	uint attenuation_energy; //attenuation
-	uint color_specular; //rgb color, a specular (8 bit unorm)
-	uint cone_attenuation_angle; // attenuation and angle, (16bit float)
-	uint shadow_color_enabled; //shadow rgb color, a>0.5 enabled (8bit unorm)
+
+	vec3 color;
+	float attenuation;
+
+	float cone_attenuation;
+	float cone_angle;
+	float specular_amount;
+	bool shadow_enabled;
+
 	vec4 atlas_rect; // rect in the shadow atlas
 	mat4 shadow_matrix;
 	float shadow_bias;
@@ -34,9 +40,13 @@ struct ReflectionData {
 	float index;
 	vec3 box_offset;
 	uint mask;
-	vec4 params; // intensity, 0, interior , boxproject
 	vec3 ambient; // ambient color
+	float intensity;
+	bool exterior;
+	bool box_project;
 	uint ambient_mode;
+	uint pad;
+	//0-8 is intensity,8-9 is ambient, mode
 	mat4 local_matrix; // up to here for spot and omni, rest is for directional
 	// notes: for ambientblend, use distance to edge to blend between already existing global environment
 };

File diff ditekan karena terlalu besar
+ 323 - 293
servers/rendering/renderer_rd/shaders/scene_forward.glsl


+ 13 - 26
servers/rendering/renderer_rd/shaders/volumetric_fog.glsl

@@ -280,19 +280,14 @@ void main() {
 
 		vec3 light_pos = lights.data[i].position;
 		float d = distance(lights.data[i].position, view_pos);
-		vec3 shadow_attenuation = vec3(1.0);
+		float shadow_attenuation = 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 = get_omni_attenuation(d, lights.data[i].inv_radius, attenuation_energy.x);
-
-			vec3 light = attenuation_energy.y * color_specular.rgb / M_PI;
+			float attenuation = get_omni_attenuation(d, lights.data[i].inv_radius, lights.data[i].attenuation);
 
-			vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[i].shadow_color_enabled);
+			vec3 light = lights.data[i].color / M_PI;
 
-			if (shadow_color_enabled.a > 0.5) {
+			if (lights.data[i].shadow_enabled) {
 				//has shadow
 				vec4 v = vec4(view_pos, 1.0);
 
@@ -319,9 +314,8 @@ void main() {
 				splane.w = 1.0; //needed? i think it should be 1 already
 
 				float depth = texture(sampler2D(shadow_atlas, linear_sampler), splane.xy).r;
-				float shadow = exp(min(0.0, (depth - splane.z)) / lights.data[i].inv_radius * lights.data[i].shadow_volumetric_fog_fade);
 
-				shadow_attenuation = mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
+				shadow_attenuation = exp(min(0.0, (depth - splane.z)) / lights.data[i].inv_radius * lights.data[i].shadow_volumetric_fog_fade);
 			}
 			total_light += light * attenuation * shadow_attenuation;
 		}
@@ -336,25 +330,19 @@ 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);
-		vec3 shadow_attenuation = vec3(1.0);
+		float shadow_attenuation = 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 = get_omni_attenuation(d, lights.data[i].inv_radius, attenuation_energy.x);
+			float attenuation = get_omni_attenuation(d, lights.data[i].inv_radius, lights.data[i].attenuation);
 
 			vec3 spot_dir = lights.data[i].direction;
-			vec2 spot_att_angle = unpackHalf2x16(lights.data[i].cone_attenuation_angle);
-			float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_att_angle.y);
-			float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_att_angle.y));
-			attenuation *= 1.0 - pow(spot_rim, spot_att_angle.x);
-
-			vec3 light = attenuation_energy.y * color_specular.rgb / M_PI;
+			float scos = max(dot(-normalize(light_rel_vec), spot_dir), lights.data[i].cone_angle);
+			float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - lights.data[i].cone_angle));
+			attenuation *= 1.0 - pow(spot_rim, lights.data[i].cone_attenuation);
 
-			vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[i].shadow_color_enabled);
+			vec3 light = lights.data[i].color / M_PI;
 
-			if (shadow_color_enabled.a > 0.5) {
+			if (lights.data[i].shadow_enabled) {
 				//has shadow
 				vec4 v = vec4(view_pos, 1.0);
 
@@ -362,9 +350,8 @@ void main() {
 				splane /= splane.w;
 
 				float depth = texture(sampler2D(shadow_atlas, linear_sampler), splane.xy).r;
-				float shadow = exp(min(0.0, (depth - splane.z)) / lights.data[i].inv_radius * lights.data[i].shadow_volumetric_fog_fade);
 
-				shadow_attenuation = mix(shadow_color_enabled.rgb, vec3(1.0), shadow);
+				shadow_attenuation = exp(min(0.0, (depth - splane.z)) / lights.data[i].inv_radius * lights.data[i].shadow_volumetric_fog_fade);
 			}
 
 			total_light += light * attenuation * shadow_attenuation;

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini