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 "st_util.h" 29#include "compiler/glsl/program.h" 30#include "compiler/nir/nir.h" 31#include "compiler/nir/nir_serialize.h" 32#include "pipe/p_shader_tokens.h" 33#include "program/ir_to_mesa.h" 34#include "tgsi/tgsi_parse.h" 35#include "util/u_memory.h" 36 37void 38st_get_program_binary_driver_sha1(struct gl_context *ctx, uint8_t *sha1) 39{ 40 disk_cache_compute_key(ctx->Cache, NULL, 0, sha1); 41} 42 43static void 44write_stream_out_to_cache(struct blob *blob, 45 struct pipe_shader_state *state) 46{ 47 blob_write_uint32(blob, state->stream_output.num_outputs); 48 if (state->stream_output.num_outputs) { 49 blob_write_bytes(blob, &state->stream_output.stride, 50 sizeof(state->stream_output.stride)); 51 blob_write_bytes(blob, &state->stream_output.output, 52 sizeof(state->stream_output.output)); 53 } 54} 55 56static void 57copy_blob_to_driver_cache_blob(struct blob *blob, struct gl_program *prog) 58{ 59 prog->driver_cache_blob = ralloc_size(NULL, blob->size); 60 memcpy(prog->driver_cache_blob, blob->data, blob->size); 61 prog->driver_cache_blob_size = blob->size; 62} 63 64static void 65write_tgsi_to_cache(struct blob *blob, const struct tgsi_token *tokens, 66 struct gl_program *prog) 67{ 68 unsigned num_tokens = tgsi_num_tokens(tokens); 69 70 blob_write_uint32(blob, num_tokens); 71 blob_write_bytes(blob, tokens, num_tokens * sizeof(struct tgsi_token)); 72 copy_blob_to_driver_cache_blob(blob, prog); 73} 74 75static void 76write_nir_to_cache(struct blob *blob, struct gl_program *prog) 77{ 78 struct st_program *stp = (struct st_program *)prog; 79 80 st_serialize_nir(stp); 81 82 blob_write_intptr(blob, stp->serialized_nir_size); 83 blob_write_bytes(blob, stp->serialized_nir, stp->serialized_nir_size); 84 85 copy_blob_to_driver_cache_blob(blob, prog); 86} 87 88static void 89st_serialise_ir_program(struct gl_context *ctx, struct gl_program *prog, 90 bool nir) 91{ 92 if (prog->driver_cache_blob) 93 return; 94 95 struct st_program *stp = (struct st_program *)prog; 96 struct blob blob; 97 blob_init(&blob); 98 99 if (prog->info.stage == MESA_SHADER_VERTEX) { 100 struct st_vertex_program *stvp = (struct st_vertex_program *)stp; 101 102 blob_write_uint32(&blob, stvp->num_inputs); 103 blob_write_uint32(&blob, stvp->vert_attrib_mask); 104 blob_write_bytes(&blob, stvp->result_to_output, 105 sizeof(stvp->result_to_output)); 106 } 107 108 if (prog->info.stage == MESA_SHADER_VERTEX || 109 prog->info.stage == MESA_SHADER_TESS_EVAL || 110 prog->info.stage == MESA_SHADER_GEOMETRY) 111 write_stream_out_to_cache(&blob, &stp->state); 112 113 if (nir) 114 write_nir_to_cache(&blob, prog); 115 else 116 write_tgsi_to_cache(&blob, stp->state.tokens, prog); 117 118 blob_finish(&blob); 119} 120 121/** 122 * Store TGSI or NIR and any other required state in on-disk shader cache. 123 */ 124void 125st_store_ir_in_disk_cache(struct st_context *st, struct gl_program *prog, 126 bool nir) 127{ 128 if (!st->ctx->Cache) 129 return; 130 131 /* Exit early when we are dealing with a ff shader with no source file to 132 * generate a source from. 133 */ 134 static const char zero[sizeof(prog->sh.data->sha1)] = {0}; 135 if (memcmp(prog->sh.data->sha1, zero, sizeof(prog->sh.data->sha1)) == 0) 136 return; 137 138 st_serialise_ir_program(st->ctx, prog, nir); 139 140 if (st->ctx->_Shader->Flags & GLSL_CACHE_INFO) { 141 fprintf(stderr, "putting %s state tracker IR in cache\n", 142 _mesa_shader_stage_to_string(prog->info.stage)); 143 } 144} 145 146static void 147read_stream_out_from_cache(struct blob_reader *blob_reader, 148 struct pipe_shader_state *state) 149{ 150 memset(&state->stream_output, 0, sizeof(state->stream_output)); 151 state->stream_output.num_outputs = blob_read_uint32(blob_reader); 152 if (state->stream_output.num_outputs) { 153 blob_copy_bytes(blob_reader, &state->stream_output.stride, 154 sizeof(state->stream_output.stride)); 155 blob_copy_bytes(blob_reader, &state->stream_output.output, 156 sizeof(state->stream_output.output)); 157 } 158} 159 160static void 161read_tgsi_from_cache(struct blob_reader *blob_reader, 162 const struct tgsi_token **tokens) 163{ 164 unsigned num_tokens = blob_read_uint32(blob_reader); 165 unsigned tokens_size = num_tokens * sizeof(struct tgsi_token); 166 *tokens = (const struct tgsi_token*) MALLOC(tokens_size); 167 blob_copy_bytes(blob_reader, (uint8_t *) *tokens, tokens_size); 168} 169 170static void 171st_deserialise_ir_program(struct gl_context *ctx, 172 struct gl_shader_program *shProg, 173 struct gl_program *prog, bool nir) 174{ 175 struct st_context *st = st_context(ctx); 176 size_t size = prog->driver_cache_blob_size; 177 uint8_t *buffer = (uint8_t *) prog->driver_cache_blob; 178 179 st_set_prog_affected_state_flags(prog); 180 181 /* Avoid reallocation of the program parameter list, because the uniform 182 * storage is only associated with the original parameter list. 183 * This should be enough for Bitmap and DrawPixels constants. 184 */ 185 _mesa_ensure_and_associate_uniform_storage(ctx, shProg, prog, 16); 186 187 assert(prog->driver_cache_blob && prog->driver_cache_blob_size > 0); 188 189 struct st_program *stp = st_program(prog); 190 struct blob_reader blob_reader; 191 blob_reader_init(&blob_reader, buffer, size); 192 193 st_release_variants(st, stp); 194 195 if (prog->info.stage == MESA_SHADER_VERTEX) { 196 struct st_vertex_program *stvp = (struct st_vertex_program *)stp; 197 stvp->num_inputs = blob_read_uint32(&blob_reader); 198 stvp->vert_attrib_mask = blob_read_uint32(&blob_reader); 199 blob_copy_bytes(&blob_reader, (uint8_t *) stvp->result_to_output, 200 sizeof(stvp->result_to_output)); 201 } 202 203 if (prog->info.stage == MESA_SHADER_VERTEX || 204 prog->info.stage == MESA_SHADER_TESS_EVAL || 205 prog->info.stage == MESA_SHADER_GEOMETRY) 206 read_stream_out_from_cache(&blob_reader, &stp->state); 207 208 if (nir) { 209 assert(prog->nir == NULL); 210 assert(stp->serialized_nir == NULL); 211 212 stp->state.type = PIPE_SHADER_IR_NIR; 213 stp->serialized_nir_size = blob_read_intptr(&blob_reader); 214 stp->serialized_nir = malloc(stp->serialized_nir_size); 215 blob_copy_bytes(&blob_reader, stp->serialized_nir, stp->serialized_nir_size); 216 stp->shader_program = shProg; 217 } else { 218 read_tgsi_from_cache(&blob_reader, &stp->state.tokens); 219 } 220 221 /* Make sure we don't try to read more data than we wrote. This should 222 * never happen in release builds but its useful to have this check to 223 * catch development bugs. 224 */ 225 if (blob_reader.current != blob_reader.end || blob_reader.overrun) { 226 assert(!"Invalid TGSI shader disk cache item!"); 227 228 if (ctx->_Shader->Flags & GLSL_CACHE_INFO) { 229 fprintf(stderr, "Error reading program from cache (invalid " 230 "TGSI cache item)\n"); 231 } 232 } 233 234 st_finalize_program(st, prog); 235} 236 237bool 238st_load_ir_from_disk_cache(struct gl_context *ctx, 239 struct gl_shader_program *prog, 240 bool nir) 241{ 242 if (!ctx->Cache) 243 return false; 244 245 /* If we didn't load the GLSL metadata from cache then we could not have 246 * loaded TGSI or NIR either. 247 */ 248 if (prog->data->LinkStatus != LINKING_SKIPPED) 249 return false; 250 251 for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { 252 if (prog->_LinkedShaders[i] == NULL) 253 continue; 254 255 struct gl_program *glprog = prog->_LinkedShaders[i]->Program; 256 st_deserialise_ir_program(ctx, prog, glprog, nir); 257 258 /* We don't need the cached blob anymore so free it */ 259 ralloc_free(glprog->driver_cache_blob); 260 glprog->driver_cache_blob = NULL; 261 glprog->driver_cache_blob_size = 0; 262 263 if (ctx->_Shader->Flags & GLSL_CACHE_INFO) { 264 fprintf(stderr, "%s state tracker IR retrieved from cache\n", 265 _mesa_shader_stage_to_string(i)); 266 } 267 } 268 269 return true; 270} 271 272void 273st_serialise_tgsi_program(struct gl_context *ctx, struct gl_program *prog) 274{ 275 st_serialise_ir_program(ctx, prog, false); 276} 277 278void 279st_serialise_tgsi_program_binary(struct gl_context *ctx, 280 struct gl_shader_program *shProg, 281 struct gl_program *prog) 282{ 283 st_serialise_ir_program(ctx, prog, false); 284} 285 286void 287st_deserialise_tgsi_program(struct gl_context *ctx, 288 struct gl_shader_program *shProg, 289 struct gl_program *prog) 290{ 291 st_deserialise_ir_program(ctx, shProg, prog, false); 292} 293 294void 295st_serialise_nir_program(struct gl_context *ctx, struct gl_program *prog) 296{ 297 st_serialise_ir_program(ctx, prog, true); 298} 299 300void 301st_serialise_nir_program_binary(struct gl_context *ctx, 302 struct gl_shader_program *shProg, 303 struct gl_program *prog) 304{ 305 st_serialise_ir_program(ctx, prog, true); 306} 307 308void 309st_deserialise_nir_program(struct gl_context *ctx, 310 struct gl_shader_program *shProg, 311 struct gl_program *prog) 312{ 313 st_deserialise_ir_program(ctx, shProg, prog, true); 314} 315