Browse Source

obs-filters: Reduced GPU work for common LUT cases

Add "Passthrough Alpha" checkbox where alpha doesn't need sanitization.

Remove domain checks, Intel UHD Graphics 750: 591 µs -> 532 µs
Alpha passthrough, Intel UHD Graphics 750: 532 µs -> 486 µs
jpark37 3 years ago
parent
commit
6eec19771a

+ 38 - 14
plugins/obs-filters/color-grade-filter.c

@@ -8,9 +8,11 @@
 
 
 #define SETTING_IMAGE_PATH             "image_path"
 #define SETTING_IMAGE_PATH             "image_path"
 #define SETTING_CLUT_AMOUNT            "clut_amount"
 #define SETTING_CLUT_AMOUNT            "clut_amount"
+#define SETTING_PASSTHROUGH_ALPHA      "passthrough_alpha"
 
 
 #define TEXT_IMAGE_PATH                obs_module_text("Path")
 #define TEXT_IMAGE_PATH                obs_module_text("Path")
 #define TEXT_AMOUNT                    obs_module_text("Amount")
 #define TEXT_AMOUNT                    obs_module_text("Amount")
+#define TEXT_PASSTHROUGH_ALPHA         obs_module_text("PassthroughAlpha")
 
 
 /* clang-format on */
 /* clang-format on */
 
 
@@ -33,11 +35,12 @@ struct lut_filter_data {
 
 
 	char *file;
 	char *file;
 	float clut_amount;
 	float clut_amount;
-	enum clut_dimension clut_dim;
 	struct vec3 clut_scale;
 	struct vec3 clut_scale;
 	struct vec3 clut_offset;
 	struct vec3 clut_offset;
 	struct vec3 domain_min;
 	struct vec3 domain_min;
 	struct vec3 domain_max;
 	struct vec3 domain_max;
+	const char *clut_texture_name;
+	const char *tech_name;
 };
 };
 
 
 static const char *color_grade_filter_get_name(void *unused)
 static const char *color_grade_filter_get_name(void *unused)
@@ -253,6 +256,8 @@ static void color_grade_filter_update(void *data, obs_data_t *settings)
 
 
 	const double clut_amount =
 	const double clut_amount =
 		obs_data_get_double(settings, SETTING_CLUT_AMOUNT);
 		obs_data_get_double(settings, SETTING_CLUT_AMOUNT);
+	const bool passthrough_alpha =
+		obs_data_get_bool(settings, SETTING_PASSTHROUGH_ALPHA);
 
 
 	bfree(filter->file);
 	bfree(filter->file);
 	if (path)
 	if (path)
@@ -269,6 +274,10 @@ static void color_grade_filter_update(void *data, obs_data_t *settings)
 	filter->target = NULL;
 	filter->target = NULL;
 	obs_leave_graphics();
 	obs_leave_graphics();
 
 
+	enum clut_dimension clut_dim = CLUT_3D;
+	const char *clut_texture_name = "clut_3d";
+	const char *tech_name = "Draw3D";
+
 	if (path) {
 	if (path) {
 		vec3_set(&filter->domain_min, 0.0f, 0.0f, 0.0f);
 		vec3_set(&filter->domain_min, 0.0f, 0.0f, 0.0f);
 		vec3_set(&filter->domain_max, 1.0f, 1.0f, 1.0f);
 		vec3_set(&filter->domain_max, 1.0f, 1.0f, 1.0f);
@@ -277,11 +286,26 @@ static void color_grade_filter_update(void *data, obs_data_t *settings)
 		if (ext && astrcmpi(ext, ".cube") == 0) {
 		if (ext && astrcmpi(ext, ".cube") == 0) {
 			filter->cube_data = load_cube_file(
 			filter->cube_data = load_cube_file(
 				path, &filter->cube_width, &filter->domain_min,
 				path, &filter->cube_width, &filter->domain_min,
-				&filter->domain_max, &filter->clut_dim);
+				&filter->domain_max, &clut_dim);
 		} else {
 		} else {
 			gs_image_file_init(&filter->image, path);
 			gs_image_file_init(&filter->image, path);
 			filter->cube_width = LUT_WIDTH;
 			filter->cube_width = LUT_WIDTH;
-			filter->clut_dim = CLUT_3D;
+		}
+
+		if (clut_dim == CLUT_1D) {
+			clut_texture_name = "clut_1d";
+			tech_name = "Draw1D";
+		} else if ((filter->domain_min.x > 0.f) ||
+			   (filter->domain_min.y > 0.f) ||
+			   (filter->domain_min.z > 0.f) ||
+			   (filter->domain_max.x < 1.f) ||
+			   (filter->domain_max.y < 1.f) ||
+			   (filter->domain_max.z < 1.f)) {
+			tech_name = "DrawDomain3D";
+		} else if (clut_amount < 1.0) {
+			tech_name = "DrawAmount3D";
+		} else if (!passthrough_alpha) {
+			tech_name = "DrawAlpha3D";
 		}
 		}
 	}
 	}
 
 
@@ -300,7 +324,7 @@ static void color_grade_filter_update(void *data, obs_data_t *settings)
 			vec3_set(&filter->clut_offset, offset, offset, offset);
 			vec3_set(&filter->clut_offset, offset, offset, offset);
 		} else if (filter->cube_data) {
 		} else if (filter->cube_data) {
 			const uint32_t width = filter->cube_width;
 			const uint32_t width = filter->cube_width;
-			if (filter->clut_dim == CLUT_1D) {
+			if (clut_dim == CLUT_1D) {
 				filter->target = gs_texture_create(
 				filter->target = gs_texture_create(
 					width, 1, GS_RGBA16F, 1,
 					width, 1, GS_RGBA16F, 1,
 					(const uint8_t **)&filter->cube_data,
 					(const uint8_t **)&filter->cube_data,
@@ -337,6 +361,8 @@ static void color_grade_filter_update(void *data, obs_data_t *settings)
 	}
 	}
 
 
 	filter->clut_amount = (float)clut_amount;
 	filter->clut_amount = (float)clut_amount;
+	filter->clut_texture_name = clut_texture_name;
+	filter->tech_name = tech_name;
 
 
 	char *effect_path = obs_module_file("color_grade_filter.effect");
 	char *effect_path = obs_module_file("color_grade_filter.effect");
 	gs_effect_destroy(filter->effect);
 	gs_effect_destroy(filter->effect);
@@ -348,7 +374,8 @@ static void color_grade_filter_update(void *data, obs_data_t *settings)
 
 
 static void color_grade_filter_defaults(obs_data_t *settings)
 static void color_grade_filter_defaults(obs_data_t *settings)
 {
 {
-	obs_data_set_default_double(settings, SETTING_CLUT_AMOUNT, 1);
+	obs_data_set_default_double(settings, SETTING_CLUT_AMOUNT, 1.0);
+	obs_data_set_default_bool(settings, SETTING_PASSTHROUGH_ALPHA, false);
 }
 }
 
 
 static obs_properties_t *color_grade_filter_properties(void *data)
 static obs_properties_t *color_grade_filter_properties(void *data)
@@ -380,6 +407,8 @@ static obs_properties_t *color_grade_filter_properties(void *data)
 				OBS_PATH_FILE, filter_str.array, path.array);
 				OBS_PATH_FILE, filter_str.array, path.array);
 	obs_properties_add_float_slider(props, SETTING_CLUT_AMOUNT, TEXT_AMOUNT,
 	obs_properties_add_float_slider(props, SETTING_CLUT_AMOUNT, TEXT_AMOUNT,
 					0, 1, 0.0001);
 					0, 1, 0.0001);
+	obs_properties_add_bool(props, SETTING_PASSTHROUGH_ALPHA,
+				TEXT_PASSTHROUGH_ALPHA);
 
 
 	dstr_free(&filter_str);
 	dstr_free(&filter_str);
 	dstr_free(&path);
 	dstr_free(&path);
@@ -426,17 +455,12 @@ static void color_grade_filter_render(void *data, gs_effect_t *effect)
 	}
 	}
 
 
 	if (!obs_source_process_filter_begin(filter->context, GS_RGBA,
 	if (!obs_source_process_filter_begin(filter->context, GS_RGBA,
-					     OBS_ALLOW_DIRECT_RENDERING))
+					     OBS_ALLOW_DIRECT_RENDERING)) {
 		return;
 		return;
-
-	const char *clut_texture_name = "clut_3d";
-	const char *tech_name = "Draw3D";
-	if (filter->clut_dim == CLUT_1D) {
-		clut_texture_name = "clut_1d";
-		tech_name = "Draw1D";
 	}
 	}
 
 
-	param = gs_effect_get_param_by_name(filter->effect, clut_texture_name);
+	param = gs_effect_get_param_by_name(filter->effect,
+					    filter->clut_texture_name);
 	gs_effect_set_texture_srgb(param, filter->target);
 	gs_effect_set_texture_srgb(param, filter->target);
 
 
 	param = gs_effect_get_param_by_name(filter->effect, "clut_amount");
 	param = gs_effect_get_param_by_name(filter->effect, "clut_amount");
@@ -458,7 +482,7 @@ static void color_grade_filter_render(void *data, gs_effect_t *effect)
 	gs_blend_function(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA);
 	gs_blend_function(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA);
 
 
 	obs_source_process_filter_tech_end(filter->context, filter->effect, 0,
 	obs_source_process_filter_tech_end(filter->context, filter->effect, 0,
-					   0, tech_name);
+					   0, filter->tech_name);
 
 
 	gs_blend_state_pop();
 	gs_blend_state_pop();
 
 

+ 65 - 0
plugins/obs-filters/data/color_grade_filter.effect

@@ -72,6 +72,44 @@ float4 LUT1D(VertDataOut v_in) : TARGET
 }
 }
 
 
 float4 LUT3D(VertDataOut v_in) : TARGET
 float4 LUT3D(VertDataOut v_in) : TARGET
+{
+	float4 textureColor = image.Sample(textureSampler, v_in.uv);
+	float3 nonlinear = srgb_linear_to_nonlinear(textureColor.rgb);
+
+	float3 clut_uvw = nonlinear * clut_scale + clut_offset;
+	textureColor.rgb = clut_3d.Sample(textureSampler, clut_uvw).rgb;
+
+	return textureColor;
+}
+
+float4 LUTAlpha3D(VertDataOut v_in) : TARGET
+{
+	float4 textureColor = image.Sample(textureSampler, v_in.uv);
+	textureColor.rgb = max(float3(0.0, 0.0, 0.0), textureColor.rgb / textureColor.a);
+	float3 nonlinear = srgb_linear_to_nonlinear(textureColor.rgb);
+
+	float3 clut_uvw = nonlinear * clut_scale + clut_offset;
+	textureColor.rgb = clut_3d.Sample(textureSampler, clut_uvw).rgb;
+
+	textureColor.rgb *= textureColor.a;
+	return textureColor;
+}
+
+float4 LUTAmount3D(VertDataOut v_in) : TARGET
+{
+	float4 textureColor = image.Sample(textureSampler, v_in.uv);
+	textureColor.rgb = max(float3(0.0, 0.0, 0.0), textureColor.rgb / textureColor.a);
+	float3 nonlinear = srgb_linear_to_nonlinear(textureColor.rgb);
+
+	float3 clut_uvw = nonlinear * clut_scale + clut_offset;
+	float3 luttedColor = clut_3d.Sample(textureSampler, clut_uvw).rgb;
+	textureColor.rgb = lerp(textureColor.rgb, luttedColor, clut_amount);
+
+	textureColor.rgb *= textureColor.a;
+	return textureColor;
+}
+
+float4 LUTDomain3D(VertDataOut v_in) : TARGET
 {
 {
 	float4 textureColor = image.Sample(textureSampler, v_in.uv);
 	float4 textureColor = image.Sample(textureSampler, v_in.uv);
 	textureColor.rgb = max(float3(0.0, 0.0, 0.0), textureColor.rgb / textureColor.a);
 	textureColor.rgb = max(float3(0.0, 0.0, 0.0), textureColor.rgb / textureColor.a);
@@ -110,3 +148,30 @@ technique Draw3D
 		pixel_shader  = LUT3D(v_in);
 		pixel_shader  = LUT3D(v_in);
 	}
 	}
 }
 }
+
+technique DrawAlpha3D
+{
+	pass
+	{
+		vertex_shader = VSDefault(v_in);
+		pixel_shader  = LUTAlpha3D(v_in);
+	}
+}
+
+technique DrawAmount3D
+{
+	pass
+	{
+		vertex_shader = VSDefault(v_in);
+		pixel_shader  = LUTAmount3D(v_in);
+	}
+}
+
+technique DrawDomain3D
+{
+	pass
+	{
+		vertex_shader = VSDefault(v_in);
+		pixel_shader  = LUTDomain3D(v_in);
+	}
+}

+ 1 - 0
plugins/obs-filters/data/locale/en-US.ini

@@ -79,6 +79,7 @@ NoiseSuppress.Method.nvafx="NVIDIA Noise Removal (good quality, no CPU usage)"
 Saturation="Saturation"
 Saturation="Saturation"
 HueShift="Hue Shift"
 HueShift="Hue Shift"
 Amount="Amount"
 Amount="Amount"
+PassthroughAlpha="Passthrough Alpha"
 Compressor="Compressor"
 Compressor="Compressor"
 Compressor.Ratio="Ratio"
 Compressor.Ratio="Ratio"
 Compressor.Threshold="Threshold"
 Compressor.Threshold="Threshold"