Browse Source

st/mesa: keep serialized NIR instead of nir_shader in st_program

This decreases memory usage, because serialized NIR is more compact.

If shader_has_one_variant is true and the shader is uncached, the first
variant is created from nir_shader, otherwise the first variant and
all other variants are created from serialized NIR.

Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
master
Marek Olšák 5 years ago
parent
commit
db0c89d4bf

+ 2
- 0
src/mesa/state_tracker/st_cb_program.c View File

if (stp->glsl_to_tgsi) if (stp->glsl_to_tgsi)
free_glsl_to_tgsi_visitor(stp->glsl_to_tgsi); free_glsl_to_tgsi_visitor(stp->glsl_to_tgsi);


free(stp->nir_binary);

/* delete base class */ /* delete base class */
_mesa_delete_program( ctx, prog ); _mesa_delete_program( ctx, prog );
} }

+ 42
- 6
src/mesa/state_tracker/st_program.c View File

#include "program/prog_to_nir.h" #include "program/prog_to_nir.h"
#include "program/programopt.h" #include "program/programopt.h"


#include "compiler/nir/nir.h"
#include "compiler/nir/nir_serialize.h"


#include "pipe/p_context.h" #include "pipe/p_context.h"
#include "pipe/p_defines.h" #include "pipe/p_defines.h"
return stp->state.tokens != NULL; return stp->state.tokens != NULL;
} }


static struct nir_shader *
get_nir_shader(struct st_context *st, struct st_program *stp)
{
if (stp->state.ir.nir)
return nir_shader_clone(NULL, stp->state.ir.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->nir_binary, stp->nir_size);
return nir_deserialize(NULL, options, &blob_reader);
}

static const gl_state_index16 depth_range_state[STATE_LENGTH] = static const gl_state_index16 depth_range_state[STATE_LENGTH] =
{ STATE_DEPTH_RANGE }; { STATE_DEPTH_RANGE };


bool finalize = false; bool finalize = false;


state.type = PIPE_SHADER_IR_NIR; state.type = PIPE_SHADER_IR_NIR;
state.ir.nir = nir_shader_clone(NULL, stvp->state.ir.nir);
state.ir.nir = get_nir_shader(st, stvp);
if (key->clamp_color) { if (key->clamp_color) {
NIR_PASS_V(state.ir.nir, nir_lower_clamp_color_outputs); NIR_PASS_V(state.ir.nir, nir_lower_clamp_color_outputs);
finalize = true; finalize = true;
bool finalize = false; bool finalize = false;


state.type = PIPE_SHADER_IR_NIR; state.type = PIPE_SHADER_IR_NIR;
state.ir.nir = nir_shader_clone(NULL, stfp->state.ir.nir);
state.ir.nir = get_nir_shader(st, stfp);


if (key->clamp_color) { if (key->clamp_color) {
NIR_PASS_V(state.ir.nir, nir_lower_clamp_color_outputs); NIR_PASS_V(state.ir.nir, nir_lower_clamp_color_outputs);
bool finalize = false; bool finalize = false;


state.type = PIPE_SHADER_IR_NIR; state.type = PIPE_SHADER_IR_NIR;
state.ir.nir = nir_shader_clone(NULL, prog->state.ir.nir);
state.ir.nir = get_nir_shader(st, prog);


if (key->clamp_color) { if (key->clamp_color) {
NIR_PASS_V(state.ir.nir, nir_lower_clamp_color_outputs); NIR_PASS_V(state.ir.nir, nir_lower_clamp_color_outputs);
void void
st_finalize_program(struct st_context *st, struct gl_program *prog) st_finalize_program(struct st_context *st, struct gl_program *prog)
{ {
struct st_program *stp = (struct st_program *)prog;

if (st->current_program[prog->info.stage] == prog) { if (st->current_program[prog->info.stage] == prog) {
if (prog->info.stage == MESA_SHADER_VERTEX) if (prog->info.stage == MESA_SHADER_VERTEX)
st->dirty |= ST_NEW_VERTEX_PROGRAM(st, (struct st_program *)prog);
st->dirty |= ST_NEW_VERTEX_PROGRAM(st, stp);
else else
st->dirty |= ((struct st_program *)prog)->affected_states;
st->dirty |= stp->affected_states;
} }


if (prog->nir) if (prog->nir)
if (ST_DEBUG & DEBUG_PRECOMPILE || if (ST_DEBUG & DEBUG_PRECOMPILE ||
st->shader_has_one_variant[prog->info.stage]) st->shader_has_one_variant[prog->info.stage])
st_precompile_shader_variant(st, prog); st_precompile_shader_variant(st, prog);

/* Additional shader variants are always generated from serialized NIR
* to save memory.
*/
if (prog->nir) {
/* Serialize NIR. */
struct blob blob;
blob_init(&blob);
nir_serialize(&blob, prog->nir, false);
stp->nir_binary = malloc(blob.size);
memcpy(stp->nir_binary, blob.data, blob.size);
stp->nir_size = blob.size;
blob_finish(&blob);

/* Free NIR. */
assert(stp->state.ir.nir == prog->nir);
ralloc_free(prog->nir);
prog->nir = NULL;
stp->state.ir.nir = NULL;
}
} }

+ 3
- 0
src/mesa/state_tracker/st_program.h View File

struct ati_fragment_shader *ati_fs; struct ati_fragment_shader *ati_fs;
uint64_t affected_states; /**< ST_NEW_* flags to mark dirty when binding */ uint64_t affected_states; /**< ST_NEW_* flags to mark dirty when binding */


void *nir_binary;
unsigned nir_size;

/* used when bypassing glsl_to_tgsi: */ /* used when bypassing glsl_to_tgsi: */
struct gl_shader_program *shader_program; struct gl_shader_program *shader_program;



+ 22
- 5
src/mesa/state_tracker/st_shader_cache.c View File

static void static void
write_nir_to_cache(struct blob *blob, struct gl_program *prog) write_nir_to_cache(struct blob *blob, struct gl_program *prog)
{ {
nir_serialize(blob, prog->nir, false);
if (prog->nir) {
/* Reserve intptr_t to store the size. intptr_t is also the alignment
* of NIR in the blob, so the NIR size computation will be trivial.
*/
size_t offset = blob_reserve_intptr(blob);
nir_serialize(blob, prog->nir, false);

unsigned nir_size = blob->size - offset - sizeof(intptr_t);
*(uintptr_t *)(blob->data + offset) = nir_size;
} else {
struct st_program *stp = (struct st_program *)prog;
blob_write_intptr(blob, stp->nir_size);
blob_write_bytes(blob, stp->nir_binary, stp->nir_size);
}
copy_blob_to_driver_cache_blob(blob, prog); copy_blob_to_driver_cache_blob(blob, prog);
} }


struct st_context *st = st_context(ctx); struct st_context *st = st_context(ctx);
size_t size = prog->driver_cache_blob_size; size_t size = prog->driver_cache_blob_size;
uint8_t *buffer = (uint8_t *) prog->driver_cache_blob; uint8_t *buffer = (uint8_t *) prog->driver_cache_blob;
const struct nir_shader_compiler_options *options =
ctx->Const.ShaderCompilerOptions[prog->info.stage].NirOptions;


st_set_prog_affected_state_flags(prog); st_set_prog_affected_state_flags(prog);
_mesa_associate_uniform_storage(ctx, shProg, prog); _mesa_associate_uniform_storage(ctx, shProg, prog);
read_stream_out_from_cache(&blob_reader, &stp->state); read_stream_out_from_cache(&blob_reader, &stp->state);


if (nir) { if (nir) {
assert(prog->nir == NULL);
assert(stp->state.ir.nir == NULL);
assert(stp->nir_binary == NULL);

/* The remainder of the binary is NIR. */
stp->state.type = PIPE_SHADER_IR_NIR; stp->state.type = PIPE_SHADER_IR_NIR;
stp->state.ir.nir = nir_deserialize(NULL, options, &blob_reader);
stp->nir_size = blob_read_intptr(&blob_reader);
stp->nir_binary = malloc(stp->nir_size);
blob_copy_bytes(&blob_reader, stp->nir_binary, stp->nir_size);
stp->shader_program = shProg; stp->shader_program = shProg;
prog->nir = stp->state.ir.nir;
} else { } else {
read_tgsi_from_cache(&blob_reader, &stp->state.tokens); read_tgsi_from_cache(&blob_reader, &stp->state.tokens);
} }

Loading…
Cancel
Save