#include "program/programopt.h"
#include "compiler/nir/nir.h"
+#include "compiler/nir/nir_serialize.h"
#include "draw/draw_context.h"
#include "pipe/p_context.h"
if (stp->Base.nir)
ralloc_free(stp->Base.nir);
+ if (stp->serialized_nir) {
+ free(stp->serialized_nir);
+ stp->serialized_nir = NULL;
+ }
+
stp->state.type = PIPE_SHADER_IR_NIR;
stp->Base.nir = st_translate_prog_to_nir(st, &stp->Base,
MESA_SHADER_VERTEX);
return stp->state.tokens != NULL;
}
+static struct nir_shader *
+get_nir_shader(struct st_context *st, struct st_program *stp)
+{
+ if (stp->Base.nir) {
+ nir_shader *nir = stp->Base.nir;
+
+ /* The first shader variant takes ownership of NIR, so that there is
+ * no cloning. Additional shader variants are always generated from
+ * serialized NIR to save memory.
+ */
+ stp->Base.nir = NULL;
+ assert(stp->serialized_nir && stp->serialized_nir_size);
+ return nir;
+ }
+
+ struct blob_reader blob_reader;
+ const struct nir_shader_compiler_options *options =
+ st->ctx->Const.ShaderCompilerOptions[stp->Base.info.stage].NirOptions;
+
+ blob_reader_init(&blob_reader, stp->serialized_nir, stp->serialized_nir_size);
+ return nir_deserialize(NULL, options, &blob_reader);
+}
+
static const gl_state_index16 depth_range_state[STATE_LENGTH] =
{ STATE_DEPTH_RANGE };
bool finalize = false;
state.type = PIPE_SHADER_IR_NIR;
- state.ir.nir = nir_shader_clone(NULL, stvp->Base.nir);
+ state.ir.nir = get_nir_shader(st, stvp);
if (key->clamp_color) {
NIR_PASS_V(state.ir.nir, nir_lower_clamp_color_outputs);
finalize = true;
if (stfp->Base.nir)
ralloc_free(stfp->Base.nir);
+ if (stfp->serialized_nir) {
+ free(stfp->serialized_nir);
+ stfp->serialized_nir = NULL;
+ }
stfp->state.type = PIPE_SHADER_IR_NIR;
stfp->Base.nir = nir;
return true;
bool finalize = false;
state.type = PIPE_SHADER_IR_NIR;
- state.ir.nir = nir_shader_clone(NULL, stfp->Base.nir);
+ state.ir.nir = get_nir_shader(st, stfp);
if (key->clamp_color) {
NIR_PASS_V(state.ir.nir, nir_lower_clamp_color_outputs);
bool finalize = false;
state.type = PIPE_SHADER_IR_NIR;
- state.ir.nir = nir_shader_clone(NULL, prog->Base.nir);
+ state.ir.nir = get_nir_shader(st, prog);
if (key->clamp_color) {
NIR_PASS_V(state.ir.nir, nir_lower_clamp_color_outputs);
}
}
+void
+st_serialize_nir(struct st_program *stp)
+{
+ if (!stp->serialized_nir) {
+ struct blob blob;
+ size_t size;
+
+ blob_init(&blob);
+ nir_serialize(&blob, stp->Base.nir, false);
+ blob_finish_get_buffer(&blob, &stp->serialized_nir, &size);
+ stp->serialized_nir_size = size;
+ }
+}
+
void
st_finalize_program(struct st_context *st, struct gl_program *prog)
{
st->dirty |= ((struct st_program *)prog)->affected_states;
}
- if (prog->nir)
+ if (prog->nir) {
nir_sweep(prog->nir);
+ /* This is only needed for ARB_vp/fp programs and when the disk cache
+ * is disabled. If the disk cache is enabled, GLSL programs are
+ * serialized in write_nir_to_cache.
+ */
+ st_serialize_nir(st_program(prog));
+ }
+
/* Create Gallium shaders now instead of on demand. */
if (ST_DEBUG & DEBUG_PRECOMPILE ||
st->shader_has_one_variant[prog->info.stage])