Browse Source

libobs: UI: Remove DrawBackdrop() to save fullscreen pass

It's a waste of GPU time to do two fullscreen passes to render final mix
previews. Use blend states to simulate the black background of
DrawBackdrop() for the following situations:

- Main preview window (Studio Mode off)
- Studio Mode: Program

This does not effect:

- Studio Mode: Preview (still uses DrawBackdrop)
- Fullscreen Projector (uses GPU clear to black)
- Windowed Projector (uses GPU clear to black)

intel GPA, SetStablePowerState, Intel HD Graphics 530, 1920x1080

Before:
DrawBackdrop: ~529 us
main texture: ~367 us (Cheaper than drawing a black quad?)

After:
[DrawBackdrop optimized away]
main texture: ~383 us
jpark37 6 years ago
parent
commit
3456ed0644
4 changed files with 25 additions and 8 deletions
  1. 1 3
      UI/window-basic-main-transitions.cpp
  2. 4 3
      UI/window-basic-main.cpp
  3. 17 2
      libobs/obs.c
  4. 3 0
      libobs/obs.h

+ 1 - 3
UI/window-basic-main-transitions.cpp

@@ -1330,9 +1330,7 @@ void OBSBasic::RenderProgram(void *data, uint32_t cx, uint32_t cy)
 	gs_set_viewport(window->programX, window->programY, window->programCX,
 	gs_set_viewport(window->programX, window->programY, window->programCX,
 			window->programCY);
 			window->programCY);
 
 
-	window->DrawBackdrop(float(ovi.base_width), float(ovi.base_height));
-
-	obs_render_main_texture();
+	obs_render_main_texture_src_color_only();
 	gs_load_vertexbuffer(nullptr);
 	gs_load_vertexbuffer(nullptr);
 
 
 	/* --------------------------------------- */
 	/* --------------------------------------- */

+ 4 - 3
UI/window-basic-main.cpp

@@ -3341,15 +3341,16 @@ void OBSBasic::RenderMain(void *data, uint32_t cx, uint32_t cy)
 	gs_set_viewport(window->previewX, window->previewY, window->previewCX,
 	gs_set_viewport(window->previewX, window->previewY, window->previewCX,
 			window->previewCY);
 			window->previewCY);
 
 
-	window->DrawBackdrop(float(ovi.base_width), float(ovi.base_height));
-
 	if (window->IsPreviewProgramMode()) {
 	if (window->IsPreviewProgramMode()) {
+		window->DrawBackdrop(float(ovi.base_width),
+				     float(ovi.base_height));
+
 		OBSScene scene = window->GetCurrentScene();
 		OBSScene scene = window->GetCurrentScene();
 		obs_source_t *source = obs_scene_get_source(scene);
 		obs_source_t *source = obs_scene_get_source(scene);
 		if (source)
 		if (source)
 			obs_source_video_render(source);
 			obs_source_video_render(source);
 	} else {
 	} else {
-		obs_render_main_texture();
+		obs_render_main_texture_src_color_only();
 	}
 	}
 	gs_load_vertexbuffer(nullptr);
 	gs_load_vertexbuffer(nullptr);
 
 

+ 17 - 2
libobs/obs.c

@@ -1645,7 +1645,10 @@ void obs_render_main_view(void)
 	obs_view_render(&obs->data.main_view);
 	obs_view_render(&obs->data.main_view);
 }
 }
 
 
-void obs_render_main_texture(void)
+static void obs_render_main_texture_internal(enum gs_blend_type src_c,
+					     enum gs_blend_type dest_c,
+					     enum gs_blend_type src_a,
+					     enum gs_blend_type dest_a)
 {
 {
 	struct obs_core_video *video;
 	struct obs_core_video *video;
 	gs_texture_t *tex;
 	gs_texture_t *tex;
@@ -1665,7 +1668,7 @@ void obs_render_main_texture(void)
 	gs_effect_set_texture(param, tex);
 	gs_effect_set_texture(param, tex);
 
 
 	gs_blend_state_push();
 	gs_blend_state_push();
-	gs_blend_function(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA);
+	gs_blend_function_separate(src_c, dest_c, src_a, dest_a);
 
 
 	while (gs_effect_loop(effect, "Draw"))
 	while (gs_effect_loop(effect, "Draw"))
 		gs_draw_sprite(tex, 0, 0, 0);
 		gs_draw_sprite(tex, 0, 0, 0);
@@ -1673,6 +1676,18 @@ void obs_render_main_texture(void)
 	gs_blend_state_pop();
 	gs_blend_state_pop();
 }
 }
 
 
+void obs_render_main_texture(void)
+{
+	obs_render_main_texture_internal(GS_BLEND_ONE, GS_BLEND_INVSRCALPHA,
+					 GS_BLEND_ONE, GS_BLEND_INVSRCALPHA);
+}
+
+void obs_render_main_texture_src_color_only(void)
+{
+	obs_render_main_texture_internal(GS_BLEND_ONE, GS_BLEND_ZERO,
+					 GS_BLEND_ONE, GS_BLEND_INVSRCALPHA);
+}
+
 gs_texture_t *obs_get_main_texture(void)
 gs_texture_t *obs_get_main_texture(void)
 {
 {
 	struct obs_core_video *video;
 	struct obs_core_video *video;

+ 3 - 0
libobs/obs.h

@@ -649,6 +649,9 @@ EXPORT void obs_render_main_view(void);
 /** Renders the last main output texture */
 /** Renders the last main output texture */
 EXPORT void obs_render_main_texture(void);
 EXPORT void obs_render_main_texture(void);
 
 
+/** Renders the last main output texture ignoring background color */
+EXPORT void obs_render_main_texture_src_color_only(void);
+
 /** Returns the last main output texture.  This can return NULL if the texture
 /** Returns the last main output texture.  This can return NULL if the texture
  * is unavailable. */
  * is unavailable. */
 EXPORT gs_texture_t *obs_get_main_texture(void);
 EXPORT gs_texture_t *obs_get_main_texture(void);