1 /* 2 * Copyright 2017 Timothy Arceri 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24 #include <stdio.h> 25 #include "st_debug.h" 26 #include "st_program.h" 27 #include "st_shader_cache.h" 28 #include "compiler/glsl/program.h" 29 #include "pipe/p_shader_tokens.h" 30 #include "program/ir_to_mesa.h" 31 #include "util/u_memory.h" 32 33 void 34 st_get_program_binary_driver_sha1(struct gl_context *ctx, uint8_t *sha1) 35 { 36 disk_cache_compute_key(ctx->Cache, NULL, 0, sha1); 37 } 38 39 static void 40 write_stream_out_to_cache(struct blob *blob, 41 struct pipe_shader_state *tgsi) 42 { 43 blob_write_bytes(blob, &tgsi->stream_output, 44 sizeof(tgsi->stream_output)); 45 } 46 47 static void 48 write_tgsi_to_cache(struct blob *blob, const struct tgsi_token *tokens, 49 struct gl_program *prog, unsigned num_tokens) 50 { 51 blob_write_uint32(blob, num_tokens); 52 blob_write_bytes(blob, tokens, num_tokens * sizeof(struct tgsi_token)); 53 54 prog->driver_cache_blob = ralloc_size(NULL, blob->size); 55 memcpy(prog->driver_cache_blob, blob->data, blob->size); 56 prog->driver_cache_blob_size = blob->size; 57 } 58 59 void 60 st_serialise_tgsi_program(struct gl_context *ctx, struct gl_program *prog) 61 { 62 struct blob blob; 63 blob_init(&blob); 64 65 switch (prog->info.stage) { 66 case MESA_SHADER_VERTEX: { 67 struct st_vertex_program *stvp = (struct st_vertex_program *) prog; 68 69 blob_write_uint32(&blob, stvp->num_inputs); 70 blob_write_bytes(&blob, stvp->index_to_input, 71 sizeof(stvp->index_to_input)); 72 blob_write_bytes(&blob, stvp->result_to_output, 73 sizeof(stvp->result_to_output)); 74 75 write_stream_out_to_cache(&blob, &stvp->tgsi); 76 write_tgsi_to_cache(&blob, stvp->tgsi.tokens, prog, 77 stvp->num_tgsi_tokens); 78 break; 79 } 80 case MESA_SHADER_TESS_CTRL: 81 case MESA_SHADER_TESS_EVAL: 82 case MESA_SHADER_GEOMETRY: { 83 struct st_common_program *stcp = (struct st_common_program *) prog; 84 85 write_stream_out_to_cache(&blob, &stcp->tgsi); 86 write_tgsi_to_cache(&blob, stcp->tgsi.tokens, prog, 87 stcp->num_tgsi_tokens); 88 break; 89 } 90 case MESA_SHADER_FRAGMENT: { 91 struct st_fragment_program *stfp = (struct st_fragment_program *) prog; 92 93 write_tgsi_to_cache(&blob, stfp->tgsi.tokens, prog, 94 stfp->num_tgsi_tokens); 95 break; 96 } 97 case MESA_SHADER_COMPUTE: { 98 struct st_compute_program *stcp = (struct st_compute_program *) prog; 99 100 write_tgsi_to_cache(&blob, stcp->tgsi.prog, prog, 101 stcp->num_tgsi_tokens); 102 break; 103 } 104 default: 105 unreachable("Unsupported stage"); 106 } 107 108 blob_finish(&blob); 109 } 110 111 /** 112 * Store tgsi and any other required state in on-disk shader cache. 113 */ 114 void 115 st_store_tgsi_in_disk_cache(struct st_context *st, struct gl_program *prog) 116 { 117 if (!st->ctx->Cache) 118 return; 119 120 /* Exit early when we are dealing with a ff shader with no source file to 121 * generate a source from. 122 */ 123 static const char zero[sizeof(prog->sh.data->sha1)] = {0}; 124 if (memcmp(prog->sh.data->sha1, zero, sizeof(prog->sh.data->sha1)) == 0) 125 return; 126 127 st_serialise_tgsi_program(st->ctx, prog); 128 129 if (st->ctx->_Shader->Flags & GLSL_CACHE_INFO) { 130 fprintf(stderr, "putting %s tgsi_tokens in cache\n", 131 _mesa_shader_stage_to_string(prog->info.stage)); 132 } 133 } 134 135 static void 136 read_stream_out_from_cache(struct blob_reader *blob_reader, 137 struct pipe_shader_state *tgsi) 138 { 139 blob_copy_bytes(blob_reader, (uint8_t *) &tgsi->stream_output, 140 sizeof(tgsi->stream_output)); 141 } 142 143 static void 144 read_tgsi_from_cache(struct blob_reader *blob_reader, 145 const struct tgsi_token **tokens, 146 unsigned *num_tokens) 147 { 148 *num_tokens = blob_read_uint32(blob_reader); 149 unsigned tokens_size = *num_tokens * sizeof(struct tgsi_token); 150 *tokens = (const struct tgsi_token*) MALLOC(tokens_size); 151 blob_copy_bytes(blob_reader, (uint8_t *) *tokens, tokens_size); 152 } 153 154 void 155 st_deserialise_tgsi_program(struct gl_context *ctx, 156 struct gl_shader_program *shProg, 157 struct gl_program *prog) 158 { 159 struct st_context *st = st_context(ctx); 160 size_t size = prog->driver_cache_blob_size; 161 uint8_t *buffer = (uint8_t *) prog->driver_cache_blob; 162 163 struct blob_reader blob_reader; 164 blob_reader_init(&blob_reader, buffer, size); 165 166 switch (prog->info.stage) { 167 case MESA_SHADER_VERTEX: { 168 struct st_vertex_program *stvp = (struct st_vertex_program *) prog; 169 170 st_release_vp_variants(st, stvp); 171 172 stvp->num_inputs = blob_read_uint32(&blob_reader); 173 blob_copy_bytes(&blob_reader, (uint8_t *) stvp->index_to_input, 174 sizeof(stvp->index_to_input)); 175 blob_copy_bytes(&blob_reader, (uint8_t *) stvp->result_to_output, 176 sizeof(stvp->result_to_output)); 177 178 read_stream_out_from_cache(&blob_reader, &stvp->tgsi); 179 read_tgsi_from_cache(&blob_reader, &stvp->tgsi.tokens, 180 &stvp->num_tgsi_tokens); 181 182 if (st->vp == stvp) 183 st->dirty |= ST_NEW_VERTEX_PROGRAM(st, stvp); 184 185 break; 186 } 187 case MESA_SHADER_TESS_CTRL: { 188 struct st_common_program *sttcp = st_common_program(prog); 189 190 st_release_basic_variants(st, sttcp->Base.Target, 191 &sttcp->variants, &sttcp->tgsi); 192 193 read_stream_out_from_cache(&blob_reader, &sttcp->tgsi); 194 read_tgsi_from_cache(&blob_reader, &sttcp->tgsi.tokens, 195 &sttcp->num_tgsi_tokens); 196 197 if (st->tcp == sttcp) 198 st->dirty |= sttcp->affected_states; 199 200 break; 201 } 202 case MESA_SHADER_TESS_EVAL: { 203 struct st_common_program *sttep = st_common_program(prog); 204 205 st_release_basic_variants(st, sttep->Base.Target, 206 &sttep->variants, &sttep->tgsi); 207 208 read_stream_out_from_cache(&blob_reader, &sttep->tgsi); 209 read_tgsi_from_cache(&blob_reader, &sttep->tgsi.tokens, 210 &sttep->num_tgsi_tokens); 211 212 if (st->tep == sttep) 213 st->dirty |= sttep->affected_states; 214 215 break; 216 } 217 case MESA_SHADER_GEOMETRY: { 218 struct st_common_program *stgp = st_common_program(prog); 219 220 st_release_basic_variants(st, stgp->Base.Target, &stgp->variants, 221 &stgp->tgsi); 222 223 read_stream_out_from_cache(&blob_reader, &stgp->tgsi); 224 read_tgsi_from_cache(&blob_reader, &stgp->tgsi.tokens, 225 &stgp->num_tgsi_tokens); 226 227 if (st->gp == stgp) 228 st->dirty |= stgp->affected_states; 229 230 break; 231 } 232 case MESA_SHADER_FRAGMENT: { 233 struct st_fragment_program *stfp = (struct st_fragment_program *) prog; 234 235 st_release_fp_variants(st, stfp); 236 237 read_tgsi_from_cache(&blob_reader, &stfp->tgsi.tokens, 238 &stfp->num_tgsi_tokens); 239 240 if (st->fp == stfp) 241 st->dirty |= stfp->affected_states; 242 243 break; 244 } 245 case MESA_SHADER_COMPUTE: { 246 struct st_compute_program *stcp = (struct st_compute_program *) prog; 247 248 st_release_cp_variants(st, stcp); 249 250 read_tgsi_from_cache(&blob_reader, 251 (const struct tgsi_token**) &stcp->tgsi.prog, 252 &stcp->num_tgsi_tokens); 253 254 stcp->tgsi.req_local_mem = stcp->Base.info.cs.shared_size; 255 stcp->tgsi.req_private_mem = 0; 256 stcp->tgsi.req_input_mem = 0; 257 258 if (st->cp == stcp) 259 st->dirty |= stcp->affected_states; 260 261 break; 262 } 263 default: 264 unreachable("Unsupported stage"); 265 } 266 267 /* Make sure we don't try to read more data than we wrote. This should 268 * never happen in release builds but its useful to have this check to 269 * catch development bugs. 270 */ 271 if (blob_reader.current != blob_reader.end || blob_reader.overrun) { 272 assert(!"Invalid TGSI shader disk cache item!"); 273 274 if (ctx->_Shader->Flags & GLSL_CACHE_INFO) { 275 fprintf(stderr, "Error reading program from cache (invalid " 276 "TGSI cache item)\n"); 277 } 278 } 279 280 st_set_prog_affected_state_flags(prog); 281 _mesa_associate_uniform_storage(ctx, shProg, prog, false); 282 283 /* Create Gallium shaders now instead of on demand. */ 284 if (ST_DEBUG & DEBUG_PRECOMPILE || 285 st->shader_has_one_variant[prog->info.stage]) 286 st_precompile_shader_variant(st, prog); 287 } 288 289 bool 290 st_load_tgsi_from_disk_cache(struct gl_context *ctx, 291 struct gl_shader_program *prog) 292 { 293 if (!ctx->Cache) 294 return false; 295 296 /* If we didn't load the GLSL metadata from cache then we could not have 297 * loaded the tgsi either. 298 */ 299 if (prog->data->LinkStatus != linking_skipped) 300 return false; 301 302 for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { 303 if (prog->_LinkedShaders[i] == NULL) 304 continue; 305 306 struct gl_program *glprog = prog->_LinkedShaders[i]->Program; 307 st_deserialise_tgsi_program(ctx, prog, glprog); 308 309 /* We don't need the cached blob anymore so free it */ 310 ralloc_free(glprog->driver_cache_blob); 311 glprog->driver_cache_blob = NULL; 312 glprog->driver_cache_blob_size = 0; 313 314 if (ctx->_Shader->Flags & GLSL_CACHE_INFO) { 315 fprintf(stderr, "%s tgsi_tokens retrieved from cache\n", 316 _mesa_shader_stage_to_string(i)); 317 } 318 } 319 320 return true; 321 } 322