From c2d60d500bbe8d8c987e312d2a2659ca432896d4 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Wed, 22 Nov 2017 20:36:22 +0100 Subject: [PATCH] Manage intermediate textures a bit more efficiently. By holding on to them only for as long as we need to, we'll save some peak texture RAM, and _might_ in some situations get a bit less cache trashing. --- effect_chain.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/effect_chain.cpp b/effect_chain.cpp index a83a952..c9d746f 100644 --- a/effect_chain.cpp +++ b/effect_chain.cpp @@ -1882,9 +1882,18 @@ void EffectChain::render(GLuint dest_fbo, const vector &dest set generated_mipmaps; - // We choose the simplest option of having one texture per output, - // since otherwise this turns into an (albeit simple) register allocation problem. + // We keep one texture per output, but only for as long as we actually have any + // phases that need it as an input. (We don't make any effort to reorder phases + // to minimize the number of textures in play, as register allocation can be + // complicated and we rarely have much to gain, since our graphs are typically + // pretty linear.) map output_textures; + map ref_counts; + for (Phase *phase : phases) { + for (Phase *input : phase->inputs) { + ++ref_counts[input]; + } + } size_t num_phases = phases.size(); if (destinations.empty()) { @@ -1972,6 +1981,15 @@ void EffectChain::render(GLuint dest_fbo, const vector &dest if (do_phase_timing) { glEndQuery(GL_TIME_ELAPSED); } + + // Drop any input textures we don't need anymore. + for (Phase *input : phase->inputs) { + assert(ref_counts[input] > 0); + if (--ref_counts[input] == 0) { + resource_pool->release_2d_texture(output_textures[input]); + output_textures.erase(input); + } + } } for (const auto &phase_and_texnum : output_textures) { -- 2.39.2