From 699201a06eb65a6ebdffd61b1cc3e7f8f6bba4ef Mon Sep 17 00:00:00 2001 From: jp9000 Date: Sun, 8 Mar 2015 06:55:15 -0700 Subject: [PATCH] libobs: Cache effects to prevent shader duplicates Switching between shaders often can cause a performance hit, so cache effects so that they persist until the graphics subsystem is destroyed. --- libobs/graphics/effect.c | 10 ++++-- libobs/graphics/effect.h | 2 ++ libobs/graphics/graphics-internal.h | 3 ++ libobs/graphics/graphics.c | 49 +++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 2 deletions(-) diff --git a/libobs/graphics/effect.c b/libobs/graphics/effect.c index ab609b972..215302385 100644 --- a/libobs/graphics/effect.c +++ b/libobs/graphics/effect.c @@ -21,11 +21,17 @@ #include "vec3.h" #include "vec4.h" +void gs_effect_actually_destroy(gs_effect_t *effect) +{ + effect_free(effect); + bfree(effect); +} + void gs_effect_destroy(gs_effect_t *effect) { if (effect) { - effect_free(effect); - bfree(effect); + if (!effect->effect_path) + gs_effect_actually_destroy(effect); } } diff --git a/libobs/graphics/effect.h b/libobs/graphics/effect.h index 2f3ab4971..b28638222 100644 --- a/libobs/graphics/effect.h +++ b/libobs/graphics/effect.h @@ -148,6 +148,8 @@ struct gs_effect { gs_eparam_t *view_proj, *world, *scale; graphics_t *graphics; + struct gs_effect *next; + size_t loop_pass; bool looping; }; diff --git a/libobs/graphics/graphics-internal.h b/libobs/graphics/graphics-internal.h index 8f7cb306d..e4655f1cd 100644 --- a/libobs/graphics/graphics-internal.h +++ b/libobs/graphics/graphics-internal.h @@ -285,6 +285,9 @@ struct graphics_subsystem { DARRAY(uint32_t) colors; DARRAY(struct vec2) texverts[16]; + pthread_mutex_t effect_mutex; + struct gs_effect *first_effect; + pthread_mutex_t mutex; volatile long ref; diff --git a/libobs/graphics/graphics.c b/libobs/graphics/graphics.c index 3160efb93..79d5b8a45 100644 --- a/libobs/graphics/graphics.c +++ b/libobs/graphics/graphics.c @@ -115,12 +115,17 @@ static bool graphics_init(struct graphics_subsystem *graphics) graphics->exports.device_enter_context(graphics->device); + pthread_mutex_init_value(&graphics->mutex); + pthread_mutex_init_value(&graphics->effect_mutex); + if (!graphics_init_immediate_vb(graphics)) return false; if (!graphics_init_sprite_vb(graphics)) return false; if (pthread_mutex_init(&graphics->mutex, NULL) != 0) return false; + if (pthread_mutex_init(&graphics->effect_mutex, NULL) != 0) + return false; graphics->exports.device_blend_function(graphics->device, GS_BLEND_SRCALPHA, GS_BLEND_INVSRCALPHA); @@ -173,6 +178,8 @@ error: return errcode; } +extern void gs_effect_actually_destroy(gs_effect_t *effect); + void gs_destroy(graphics_t *graphics) { if (!graphics) @@ -182,15 +189,28 @@ void gs_destroy(graphics_t *graphics) gs_leave_context(); if (graphics->device) { + struct gs_effect *effect = graphics->first_effect; + + thread_graphics = graphics; graphics->exports.device_enter_context(graphics->device); + + while (effect) { + struct gs_effect *next = effect->next; + gs_effect_actually_destroy(effect); + effect = next; + } + graphics->exports.gs_vertexbuffer_destroy( graphics->sprite_buffer); graphics->exports.gs_vertexbuffer_destroy( graphics->immediate_vertbuffer); graphics->exports.device_destroy(graphics->device); + + thread_graphics = NULL; } pthread_mutex_destroy(&graphics->mutex); + pthread_mutex_destroy(&graphics->effect_mutex); da_free(graphics->matrix_stack); da_free(graphics->viewport_stack); if (graphics->module) @@ -644,6 +664,19 @@ gs_effect_t *gs_get_effect(void) return thread_graphics ? thread_graphics->cur_effect : NULL; } +static inline struct gs_effect *find_cached_effect(const char *filename) +{ + struct gs_effect *effect = thread_graphics->first_effect; + + while (effect) { + if (strcmp(effect->effect_path, filename) == 0) + break; + effect = effect->next; + } + + return effect; +} + gs_effect_t *gs_effect_create_from_file(const char *file, char **error_string) { char *file_string; @@ -652,6 +685,10 @@ gs_effect_t *gs_effect_create_from_file(const char *file, char **error_string) if (!thread_graphics || !file) return NULL; + effect = find_cached_effect(file); + if (effect) + return effect; + file_string = os_quick_read_utf8_file(file); if (!file_string) { blog(LOG_ERROR, "Could not load effect file '%s'", file); @@ -675,6 +712,7 @@ gs_effect_t *gs_effect_create(const char *effect_string, const char *filename, bool success; effect->graphics = thread_graphics; + effect->effect_path = bstrdup(filename); ep_init(&parser); success = ep_parse(&parser, effect, effect_string, filename); @@ -686,6 +724,17 @@ gs_effect_t *gs_effect_create(const char *effect_string, const char *filename, effect = NULL; } + if (effect) { + pthread_mutex_lock(&thread_graphics->effect_mutex); + + if (effect->effect_path) { + effect->next = thread_graphics->first_effect; + thread_graphics->first_effect = effect; + } + + pthread_mutex_unlock(&thread_graphics->effect_mutex); + } + ep_free(&parser); return effect; }