/** * Called via ctx->Driver.DeleteProgram() */ static void st_delete_program(struct gl_context *ctx, struct gl_program *prog) { struct st_context *st = st_context(ctx); switch( prog->Target ) { case GL_VERTEX_PROGRAM_ARB: { struct st_vertex_program *stvp = (struct st_vertex_program *) prog; st_release_vp_variants( st, stvp ); if (stvp->glsl_to_tgsi) free_glsl_to_tgsi_visitor(stvp->glsl_to_tgsi); } break; case GL_GEOMETRY_PROGRAM_NV: { struct st_geometry_program *stgp = (struct st_geometry_program *) prog; st_release_basic_variants(st, stgp->Base.Base.Target, &stgp->variants, &stgp->tgsi); if (stgp->glsl_to_tgsi) free_glsl_to_tgsi_visitor(stgp->glsl_to_tgsi); } break; case GL_FRAGMENT_PROGRAM_ARB: { struct st_fragment_program *stfp = (struct st_fragment_program *) prog; st_release_fp_variants(st, stfp); if (stfp->glsl_to_tgsi) free_glsl_to_tgsi_visitor(stfp->glsl_to_tgsi); } break; case GL_TESS_CONTROL_PROGRAM_NV: { struct st_tessctrl_program *sttcp = (struct st_tessctrl_program *) prog; st_release_basic_variants(st, sttcp->Base.Base.Target, &sttcp->variants, &sttcp->tgsi); if (sttcp->glsl_to_tgsi) free_glsl_to_tgsi_visitor(sttcp->glsl_to_tgsi); } break; case GL_TESS_EVALUATION_PROGRAM_NV: { struct st_tesseval_program *sttep = (struct st_tesseval_program *) prog; st_release_basic_variants(st, sttep->Base.Base.Target, &sttep->variants, &sttep->tgsi); if (sttep->glsl_to_tgsi) free_glsl_to_tgsi_visitor(sttep->glsl_to_tgsi); } break; case GL_COMPUTE_PROGRAM_NV: { struct st_compute_program *stcp = (struct st_compute_program *) prog; st_release_cp_variants(st, stcp); if (stcp->glsl_to_tgsi) free_glsl_to_tgsi_visitor(stcp->glsl_to_tgsi); } break; default: assert(0); /* problem */ } /* delete base class */ _mesa_delete_program( ctx, prog ); }
/** * Called via ctx->Driver.ProgramStringNotify() * Called when the program's text/code is changed. We have to free * all shader variants and corresponding gallium shaders when this happens. */ static GLboolean st_program_string_notify( struct gl_context *ctx, GLenum target, struct gl_program *prog ) { struct st_context *st = st_context(ctx); gl_shader_stage stage = _mesa_program_enum_to_shader_stage(target); if (target == GL_FRAGMENT_PROGRAM_ARB) { struct st_fragment_program *stfp = (struct st_fragment_program *) prog; st_release_fp_variants(st, stfp); if (!st_translate_fragment_program(st, stfp)) return false; if (st->fp == stfp) st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM; } else if (target == GL_GEOMETRY_PROGRAM_NV) { struct st_geometry_program *stgp = (struct st_geometry_program *) prog; st_release_basic_variants(st, stgp->Base.Base.Target, &stgp->variants, &stgp->tgsi); if (!st_translate_geometry_program(st, stgp)) return false; if (st->gp == stgp) st->dirty.st |= ST_NEW_GEOMETRY_PROGRAM; } else if (target == GL_VERTEX_PROGRAM_ARB) { struct st_vertex_program *stvp = (struct st_vertex_program *) prog; st_release_vp_variants(st, stvp); if (!st_translate_vertex_program(st, stvp)) return false; if (st->vp == stvp) st->dirty.st |= ST_NEW_VERTEX_PROGRAM; } else if (target == GL_TESS_CONTROL_PROGRAM_NV) { struct st_tessctrl_program *sttcp = (struct st_tessctrl_program *) prog; st_release_basic_variants(st, sttcp->Base.Base.Target, &sttcp->variants, &sttcp->tgsi); if (!st_translate_tessctrl_program(st, sttcp)) return false; if (st->tcp == sttcp) st->dirty.st |= ST_NEW_TESSCTRL_PROGRAM; } else if (target == GL_TESS_EVALUATION_PROGRAM_NV) { struct st_tesseval_program *sttep = (struct st_tesseval_program *) prog; st_release_basic_variants(st, sttep->Base.Base.Target, &sttep->variants, &sttep->tgsi); if (!st_translate_tesseval_program(st, sttep)) return false; if (st->tep == sttep) st->dirty.st |= ST_NEW_TESSEVAL_PROGRAM; } else if (target == GL_COMPUTE_PROGRAM_NV) { struct st_compute_program *stcp = (struct st_compute_program *) prog; st_release_cp_variants(st, stcp); if (!st_translate_compute_program(st, stcp)) return false; if (st->cp == stcp) st->dirty_cp.st |= ST_NEW_COMPUTE_PROGRAM; } else if (target == GL_FRAGMENT_SHADER_ATI) { assert(prog); struct st_fragment_program *stfp = (struct st_fragment_program *) prog; assert(stfp->ati_fs); assert(stfp->ati_fs->Program == prog); st_init_atifs_prog(ctx, prog); st_release_fp_variants(st, stfp); if (!st_translate_fragment_program(st, stfp)) return false; if (st->fp == stfp) st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM; } if (ST_DEBUG & DEBUG_PRECOMPILE || st->shader_has_one_variant[stage]) st_precompile_shader_variant(st, prog); return GL_TRUE; }
static void st_deserialise_ir_program(struct gl_context *ctx, struct gl_shader_program *shProg, struct gl_program *prog, bool nir) { struct st_context *st = st_context(ctx); size_t size = prog->driver_cache_blob_size; uint8_t *buffer = (uint8_t *) prog->driver_cache_blob; const struct nir_shader_compiler_options *options = ctx->Const.ShaderCompilerOptions[prog->info.stage].NirOptions; assert(prog->driver_cache_blob && prog->driver_cache_blob_size > 0); struct blob_reader blob_reader; blob_reader_init(&blob_reader, buffer, size); switch (prog->info.stage) { case MESA_SHADER_VERTEX: { struct st_vertex_program *stvp = (struct st_vertex_program *) prog; st_release_vp_variants(st, stvp); stvp->num_inputs = blob_read_uint32(&blob_reader); blob_copy_bytes(&blob_reader, (uint8_t *) stvp->index_to_input, sizeof(stvp->index_to_input)); blob_copy_bytes(&blob_reader, (uint8_t *) stvp->input_to_index, sizeof(stvp->input_to_index)); blob_copy_bytes(&blob_reader, (uint8_t *) stvp->result_to_output, sizeof(stvp->result_to_output)); read_stream_out_from_cache(&blob_reader, &stvp->tgsi); if (nir) { stvp->tgsi.type = PIPE_SHADER_IR_NIR; stvp->shader_program = shProg; stvp->tgsi.ir.nir = nir_deserialize(NULL, options, &blob_reader); prog->nir = stvp->tgsi.ir.nir; } else { read_tgsi_from_cache(&blob_reader, &stvp->tgsi.tokens, &stvp->num_tgsi_tokens); } if (st->vp == stvp) st->dirty |= ST_NEW_VERTEX_PROGRAM(st, stvp); break; } case MESA_SHADER_TESS_CTRL: { struct st_common_program *sttcp = st_common_program(prog); st_release_basic_variants(st, sttcp->Base.Target, &sttcp->variants, &sttcp->tgsi); read_stream_out_from_cache(&blob_reader, &sttcp->tgsi); if (nir) { sttcp->tgsi.type = PIPE_SHADER_IR_NIR; sttcp->shader_program = shProg; sttcp->tgsi.ir.nir = nir_deserialize(NULL, options, &blob_reader); prog->nir = sttcp->tgsi.ir.nir; } else { read_tgsi_from_cache(&blob_reader, &sttcp->tgsi.tokens, &sttcp->num_tgsi_tokens); } if (st->tcp == sttcp) st->dirty |= sttcp->affected_states; break; } case MESA_SHADER_TESS_EVAL: { struct st_common_program *sttep = st_common_program(prog); st_release_basic_variants(st, sttep->Base.Target, &sttep->variants, &sttep->tgsi); read_stream_out_from_cache(&blob_reader, &sttep->tgsi); if (nir) { sttep->tgsi.type = PIPE_SHADER_IR_NIR; sttep->shader_program = shProg; sttep->tgsi.ir.nir = nir_deserialize(NULL, options, &blob_reader); prog->nir = sttep->tgsi.ir.nir; } else { read_tgsi_from_cache(&blob_reader, &sttep->tgsi.tokens, &sttep->num_tgsi_tokens); } if (st->tep == sttep) st->dirty |= sttep->affected_states; break; } case MESA_SHADER_GEOMETRY: { struct st_common_program *stgp = st_common_program(prog); st_release_basic_variants(st, stgp->Base.Target, &stgp->variants, &stgp->tgsi); read_stream_out_from_cache(&blob_reader, &stgp->tgsi); if (nir) { stgp->tgsi.type = PIPE_SHADER_IR_NIR; stgp->shader_program = shProg; stgp->tgsi.ir.nir = nir_deserialize(NULL, options, &blob_reader); prog->nir = stgp->tgsi.ir.nir; } else { read_tgsi_from_cache(&blob_reader, &stgp->tgsi.tokens, &stgp->num_tgsi_tokens); } if (st->gp == stgp) st->dirty |= stgp->affected_states; break; } case MESA_SHADER_FRAGMENT: { struct st_fragment_program *stfp = (struct st_fragment_program *) prog; st_release_fp_variants(st, stfp); if (nir) { stfp->tgsi.type = PIPE_SHADER_IR_NIR; stfp->shader_program = shProg; stfp->tgsi.ir.nir = nir_deserialize(NULL, options, &blob_reader); prog->nir = stfp->tgsi.ir.nir; } else { read_tgsi_from_cache(&blob_reader, &stfp->tgsi.tokens, &stfp->num_tgsi_tokens); } if (st->fp == stfp) st->dirty |= stfp->affected_states; break; } case MESA_SHADER_COMPUTE: { struct st_compute_program *stcp = (struct st_compute_program *) prog; st_release_cp_variants(st, stcp); if (nir) { stcp->tgsi.ir_type = PIPE_SHADER_IR_NIR; stcp->shader_program = shProg; stcp->tgsi.prog = nir_deserialize(NULL, options, &blob_reader); prog->nir = (nir_shader *) stcp->tgsi.prog; } else { read_tgsi_from_cache(&blob_reader, (const struct tgsi_token**) &stcp->tgsi.prog, &stcp->num_tgsi_tokens); } stcp->tgsi.req_local_mem = stcp->Base.info.cs.shared_size; stcp->tgsi.req_private_mem = 0; stcp->tgsi.req_input_mem = 0; if (st->cp == stcp) st->dirty |= stcp->affected_states; break; } default: unreachable("Unsupported stage"); } /* Make sure we don't try to read more data than we wrote. This should * never happen in release builds but its useful to have this check to * catch development bugs. */ if (blob_reader.current != blob_reader.end || blob_reader.overrun) { assert(!"Invalid TGSI shader disk cache item!"); if (ctx->_Shader->Flags & GLSL_CACHE_INFO) { fprintf(stderr, "Error reading program from cache (invalid " "TGSI cache item)\n"); } } st_set_prog_affected_state_flags(prog); _mesa_associate_uniform_storage(ctx, shProg, prog, false); /* Create Gallium shaders now instead of on demand. */ if (ST_DEBUG & DEBUG_PRECOMPILE || st->shader_has_one_variant[prog->info.stage]) st_precompile_shader_variant(st, prog); }