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
This commit is contained in:
jpark37 2022-02-18 22:16:14 -08:00 committed by Jim
parent 873e3a0aae
commit 6eec19771a
3 changed files with 104 additions and 14 deletions

View File

@ -8,9 +8,11 @@
#define SETTING_IMAGE_PATH "image_path"
#define SETTING_CLUT_AMOUNT "clut_amount"
#define SETTING_PASSTHROUGH_ALPHA "passthrough_alpha"
#define TEXT_IMAGE_PATH obs_module_text("Path")
#define TEXT_AMOUNT obs_module_text("Amount")
#define TEXT_PASSTHROUGH_ALPHA obs_module_text("PassthroughAlpha")
/* clang-format on */
@ -33,11 +35,12 @@ struct lut_filter_data {
char *file;
float clut_amount;
enum clut_dimension clut_dim;
struct vec3 clut_scale;
struct vec3 clut_offset;
struct vec3 domain_min;
struct vec3 domain_max;
const char *clut_texture_name;
const char *tech_name;
};
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 =
obs_data_get_double(settings, SETTING_CLUT_AMOUNT);
const bool passthrough_alpha =
obs_data_get_bool(settings, SETTING_PASSTHROUGH_ALPHA);
bfree(filter->file);
if (path)
@ -269,6 +274,10 @@ static void color_grade_filter_update(void *data, obs_data_t *settings)
filter->target = NULL;
obs_leave_graphics();
enum clut_dimension clut_dim = CLUT_3D;
const char *clut_texture_name = "clut_3d";
const char *tech_name = "Draw3D";
if (path) {
vec3_set(&filter->domain_min, 0.0f, 0.0f, 0.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) {
filter->cube_data = load_cube_file(
path, &filter->cube_width, &filter->domain_min,
&filter->domain_max, &filter->clut_dim);
&filter->domain_max, &clut_dim);
} else {
gs_image_file_init(&filter->image, path);
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);
} else if (filter->cube_data) {
const uint32_t width = filter->cube_width;
if (filter->clut_dim == CLUT_1D) {
if (clut_dim == CLUT_1D) {
filter->target = gs_texture_create(
width, 1, GS_RGBA16F, 1,
(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_texture_name = clut_texture_name;
filter->tech_name = tech_name;
char *effect_path = obs_module_file("color_grade_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)
{
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)
@ -380,6 +407,8 @@ static obs_properties_t *color_grade_filter_properties(void *data)
OBS_PATH_FILE, filter_str.array, path.array);
obs_properties_add_float_slider(props, SETTING_CLUT_AMOUNT, TEXT_AMOUNT,
0, 1, 0.0001);
obs_properties_add_bool(props, SETTING_PASSTHROUGH_ALPHA,
TEXT_PASSTHROUGH_ALPHA);
dstr_free(&filter_str);
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,
OBS_ALLOW_DIRECT_RENDERING))
OBS_ALLOW_DIRECT_RENDERING)) {
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);
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);
obs_source_process_filter_tech_end(filter->context, filter->effect, 0,
0, tech_name);
0, filter->tech_name);
gs_blend_state_pop();

View File

@ -72,6 +72,44 @@ float4 LUT1D(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);
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);
}
}
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);
}
}

View File

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