libobs: obs-filters: Area upscale shader

Add a separate shader for area upscaling to take advantage of bilinear
filtering. Iterating over texels is unnecessary in the upscale case
because a target pixel can only overlap 1 or 2 texels in X and Y
directions. When only overlapping one texel, adjust UVs to sample texel
center to avoid filtering.

Also add "base_dimension" uniform to avoid unnecessary division.

Intel HD Graphics 530, 644x478 -> 1323x1080: ~836 us -> ~232 us
This commit is contained in:
jpark37
2019-07-17 21:11:18 -07:00
parent 8af49016fa
commit 85cc7c84bc
4 changed files with 135 additions and 41 deletions

View File

@@ -470,6 +470,7 @@ static void render_item_texture(struct obs_scene_item *item)
enum obs_scale_type type = item->scale_filter;
uint32_t cx = gs_texture_get_width(tex);
uint32_t cy = gs_texture_get_height(tex);
const char *tech = "Draw";
if (type != OBS_SCALE_DISABLE) {
if (type == OBS_SCALE_POINT) {
@@ -481,6 +482,7 @@ static void render_item_texture(struct obs_scene_item *item)
} else if (!close_float(item->output_scale.x, 1.0f, EPSILON) ||
!close_float(item->output_scale.y, 1.0f, EPSILON)) {
gs_eparam_t *scale_param;
gs_eparam_t *scale_i_param;
if (item->output_scale.x < 0.5f ||
item->output_scale.y < 0.5f) {
@@ -491,15 +493,26 @@ static void render_item_texture(struct obs_scene_item *item)
effect = obs->video.lanczos_effect;
} else if (type == OBS_SCALE_AREA) {
effect = obs->video.area_effect;
if ((item->output_scale.x >= 1.0f) &&
(item->output_scale.y >= 1.0f))
tech = "DrawUpscale";
}
scale_param = gs_effect_get_param_by_name(
effect, "base_dimension_i");
effect, "base_dimension");
if (scale_param) {
struct vec2 base_res_i = {(float)cx, (float)cy};
gs_effect_set_vec2(scale_param, &base_res_i);
}
scale_i_param = gs_effect_get_param_by_name(
effect, "base_dimension_i");
if (scale_i_param) {
struct vec2 base_res_i = {1.0f / (float)cx,
1.0f / (float)cy};
gs_effect_set_vec2(scale_param, &base_res_i);
gs_effect_set_vec2(scale_i_param, &base_res_i);
}
}
}
@@ -507,7 +520,7 @@ static void render_item_texture(struct obs_scene_item *item)
gs_blend_state_push();
gs_blend_function(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA);
while (gs_effect_loop(effect, "Draw"))
while (gs_effect_loop(effect, tech))
obs_source_draw(tex, 0, 0, 0, 0, 0);
gs_blend_state_pop();