From: Rob Clark <robcl...@freedesktop.org> For gallium, at least, we'll need this to manage shader's lifetimes, since in some cases both the driver and the state tracker will need to hold on to a reference for variant managing.
Use nir_shader_mutable() before doing any IR opt/lowering/etc, to ensure you are not modifying a copy someone else is also holding a reference to. In this way, unnecessary nir_shader_clone()s are avoided whenever possible. TODO: Any places missed to s/ralloc_free()/nir_shader_unref()/ outside of freedreno/ir3? Signed-off-by: Rob Clark <robcl...@freedesktop.org> --- src/gallium/drivers/vc4/vc4_program.c | 2 +- src/glsl/nir/nir.c | 2 ++ src/glsl/nir/nir.h | 43 +++++++++++++++++++++++++++++++++++ src/mesa/program/program.c | 3 ++- 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/gallium/drivers/vc4/vc4_program.c b/src/gallium/drivers/vc4/vc4_program.c index 5d7564b..9a055df 100644 --- a/src/gallium/drivers/vc4/vc4_program.c +++ b/src/gallium/drivers/vc4/vc4_program.c @@ -1723,7 +1723,7 @@ vc4_shader_ntq(struct vc4_context *vc4, enum qstage stage, c->num_uniforms); } - ralloc_free(c->s); + nir_shader_unref(c->s); return c; } diff --git a/src/glsl/nir/nir.c b/src/glsl/nir/nir.c index 2defa36..53a11f5 100644 --- a/src/glsl/nir/nir.c +++ b/src/glsl/nir/nir.c @@ -36,6 +36,8 @@ nir_shader_create(void *mem_ctx, { nir_shader *shader = ralloc(mem_ctx, nir_shader); + p_atomic_set(&shader->refcount, 1); + exec_list_make_empty(&shader->uniforms); exec_list_make_empty(&shader->inputs); exec_list_make_empty(&shader->outputs); diff --git a/src/glsl/nir/nir.h b/src/glsl/nir/nir.h index 926747c..3ab720b 100644 --- a/src/glsl/nir/nir.h +++ b/src/glsl/nir/nir.h @@ -34,6 +34,7 @@ #include "util/ralloc.h" #include "util/set.h" #include "util/bitset.h" +#include "util/u_atomic.h" #include "nir_types.h" #include "shader_enums.h" #include <stdio.h> @@ -1546,6 +1547,8 @@ typedef struct nir_shader_info { } nir_shader_info; typedef struct nir_shader { + int refcount; + /** list of uniforms (nir_variable) */ struct exec_list uniforms; @@ -1894,6 +1897,46 @@ void nir_print_instr(const nir_instr *instr, FILE *fp); nir_shader * nir_shader_clone(void *mem_ctx, const nir_shader *s); +static inline void +nir_shader_ref(nir_shader *shader) +{ + p_atomic_inc(&shader->refcount); +} + +static inline void +nir_shader_unref(nir_shader *shader) +{ + if (p_atomic_dec_zero(&shader->refcount)) { + ralloc_free(shader); + } +} + +/* A shader with only a single reference is mutable: */ +static inline bool +nir_shader_is_mutable(nir_shader *shader) +{ + return p_atomic_read(&shader->refcount) == 1; +} + +/* Convert a shader reference into a mutable shader reference. Ie. if + * there is only a single reference to the shader, then return that, + * otherwise clone and drop reference to existing shader. + * + * TODO maybe an assert that shader->refcnt == 1 in the various opt/ + * lowering passes? If only there was a good central place to put it. + */ +static inline nir_shader * +nir_shader_mutable(nir_shader *shader) +{ + if (nir_shader_is_mutable(shader)) { + return shader; + } else { + nir_shader *ns = nir_shader_clone(ralloc_parent(shader), shader); + nir_shader_unref(shader); + return ns; + } +} + #ifdef DEBUG void nir_validate_shader(nir_shader *shader); #else diff --git a/src/mesa/program/program.c b/src/mesa/program/program.c index 0e78e6a..c2da66e 100644 --- a/src/mesa/program/program.c +++ b/src/mesa/program/program.c @@ -38,6 +38,7 @@ #include "prog_parameter.h" #include "prog_instruction.h" #include "util/ralloc.h" +#include "nir.h" /** @@ -273,7 +274,7 @@ _mesa_delete_program(struct gl_context *ctx, struct gl_program *prog) } if (prog->nir) { - ralloc_free(prog->nir); + nir_shader_unref(prog->nir); } mtx_destroy(&prog->Mutex); -- 2.5.0 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev