Path: blob/21.2-virgl/src/gallium/drivers/iris/iris_disk_cache.c
4565 views
/*1* Copyright © 2018 Intel Corporation2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice shall be included11* in all copies or substantial portions of the Software.12*13* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS14* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL16* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER17* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING18* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER19* DEALINGS IN THE SOFTWARE.20*/2122/**23* @file iris_disk_cache.c24*25* Functions for interacting with the on-disk shader cache.26*/2728#include <stdio.h>29#include <stdint.h>30#include <assert.h>31#include <string.h>3233#include "compiler/nir/nir.h"34#include "util/blob.h"35#include "util/build_id.h"36#include "util/disk_cache.h"37#include "util/mesa-sha1.h"3839#include "iris_context.h"4041static bool debug = false;4243/**44* Compute a disk cache key for the given uncompiled shader and NOS key.45*/46static void47iris_disk_cache_compute_key(struct disk_cache *cache,48const struct iris_uncompiled_shader *ish,49const void *orig_prog_key,50uint32_t prog_key_size,51cache_key cache_key)52{53/* Create a copy of the program key with program_string_id zeroed out.54* It's essentially random data which we don't want to include in our55* hashing and comparisons. We'll set a proper value on a cache hit.56*/57union brw_any_prog_key prog_key;58memcpy(&prog_key, orig_prog_key, prog_key_size);59prog_key.base.program_string_id = 0;6061uint8_t data[sizeof(prog_key) + sizeof(ish->nir_sha1)];62uint32_t data_size = prog_key_size + sizeof(ish->nir_sha1);6364memcpy(data, ish->nir_sha1, sizeof(ish->nir_sha1));65memcpy(data + sizeof(ish->nir_sha1), &prog_key, prog_key_size);6667disk_cache_compute_key(cache, data, data_size, cache_key);68}6970/**71* Store the given compiled shader in the disk cache.72*73* This should only be called on newly compiled shaders. No checking is74* done to prevent repeated stores of the same shader.75*/76void77iris_disk_cache_store(struct disk_cache *cache,78const struct iris_uncompiled_shader *ish,79const struct iris_compiled_shader *shader,80const void *prog_key,81uint32_t prog_key_size)82{83#ifdef ENABLE_SHADER_CACHE84if (!cache)85return;8687gl_shader_stage stage = ish->nir->info.stage;88const struct brw_stage_prog_data *prog_data = shader->prog_data;8990cache_key cache_key;91iris_disk_cache_compute_key(cache, ish, prog_key, prog_key_size, cache_key);9293if (debug) {94char sha1[41];95_mesa_sha1_format(sha1, cache_key);96fprintf(stderr, "[mesa disk cache] storing %s\n", sha1);97}9899struct blob blob;100blob_init(&blob);101102/* We write the following data to the cache blob:103*104* 1. Prog data (must come first because it has the assembly size)105* 2. Assembly code106* 3. Number of entries in the system value array107* 4. System value array108* 5. Size (in bytes) of kernel inputs109* 6. Shader relocations110* 7. Legacy param array (only used for compute workgroup ID)111* 8. Binding table112*/113blob_write_bytes(&blob, shader->prog_data, brw_prog_data_size(stage));114blob_write_bytes(&blob, shader->map, shader->prog_data->program_size);115blob_write_uint32(&blob, shader->num_system_values);116blob_write_bytes(&blob, shader->system_values,117shader->num_system_values * sizeof(enum brw_param_builtin));118blob_write_uint32(&blob, shader->kernel_input_size);119blob_write_bytes(&blob, prog_data->relocs,120prog_data->num_relocs * sizeof(struct brw_shader_reloc));121blob_write_bytes(&blob, prog_data->param,122prog_data->nr_params * sizeof(uint32_t));123blob_write_bytes(&blob, &shader->bt, sizeof(shader->bt));124125disk_cache_put(cache, cache_key, blob.data, blob.size, NULL);126blob_finish(&blob);127#endif128}129130static const enum iris_program_cache_id cache_id_for_stage[] = {131[MESA_SHADER_VERTEX] = IRIS_CACHE_VS,132[MESA_SHADER_TESS_CTRL] = IRIS_CACHE_TCS,133[MESA_SHADER_TESS_EVAL] = IRIS_CACHE_TES,134[MESA_SHADER_GEOMETRY] = IRIS_CACHE_GS,135[MESA_SHADER_FRAGMENT] = IRIS_CACHE_FS,136[MESA_SHADER_COMPUTE] = IRIS_CACHE_CS,137};138139/**140* Search for a compiled shader in the disk cache. If found, upload it141* to the in-memory program cache so we can use it.142*/143struct iris_compiled_shader *144iris_disk_cache_retrieve(struct iris_screen *screen,145struct u_upload_mgr *uploader,146struct iris_uncompiled_shader *ish,147const void *prog_key,148uint32_t key_size)149{150#ifdef ENABLE_SHADER_CACHE151struct disk_cache *cache = screen->disk_cache;152gl_shader_stage stage = ish->nir->info.stage;153154if (!cache)155return NULL;156157cache_key cache_key;158iris_disk_cache_compute_key(cache, ish, prog_key, key_size, cache_key);159160if (debug) {161char sha1[41];162_mesa_sha1_format(sha1, cache_key);163fprintf(stderr, "[mesa disk cache] retrieving %s: ", sha1);164}165166size_t size;167void *buffer = disk_cache_get(screen->disk_cache, cache_key, &size);168169if (debug)170fprintf(stderr, "%s\n", buffer ? "found" : "missing");171172if (!buffer)173return NULL;174175const uint32_t prog_data_size = brw_prog_data_size(stage);176177struct brw_stage_prog_data *prog_data = ralloc_size(NULL, prog_data_size);178const void *assembly;179uint32_t num_system_values;180uint32_t kernel_input_size;181uint32_t *system_values = NULL;182uint32_t *so_decls = NULL;183184struct blob_reader blob;185blob_reader_init(&blob, buffer, size);186blob_copy_bytes(&blob, prog_data, prog_data_size);187assembly = blob_read_bytes(&blob, prog_data->program_size);188num_system_values = blob_read_uint32(&blob);189if (num_system_values) {190system_values =191ralloc_array(NULL, enum brw_param_builtin, num_system_values);192blob_copy_bytes(&blob, system_values,193num_system_values * sizeof(enum brw_param_builtin));194}195196kernel_input_size = blob_read_uint32(&blob);197198prog_data->relocs = NULL;199if (prog_data->num_relocs) {200struct brw_shader_reloc *relocs =201ralloc_array(NULL, struct brw_shader_reloc, prog_data->num_relocs);202blob_copy_bytes(&blob, relocs,203prog_data->num_relocs * sizeof(struct brw_shader_reloc));204prog_data->relocs = relocs;205}206207prog_data->param = NULL;208prog_data->pull_param = NULL;209assert(prog_data->nr_pull_params == 0);210211if (prog_data->nr_params) {212prog_data->param = ralloc_array(NULL, uint32_t, prog_data->nr_params);213blob_copy_bytes(&blob, prog_data->param,214prog_data->nr_params * sizeof(uint32_t));215}216217struct iris_binding_table bt;218blob_copy_bytes(&blob, &bt, sizeof(bt));219220if (stage == MESA_SHADER_VERTEX ||221stage == MESA_SHADER_TESS_EVAL ||222stage == MESA_SHADER_GEOMETRY) {223struct brw_vue_prog_data *vue_prog_data = (void *) prog_data;224so_decls = screen->vtbl.create_so_decl_list(&ish->stream_output,225&vue_prog_data->vue_map);226}227228/* System values and uniforms are stored in constant buffer 0, the229* user-facing UBOs are indexed by one. So if any constant buffer is230* needed, the constant buffer 0 will be needed, so account for it.231*/232unsigned num_cbufs = ish->nir->info.num_ubos;233234if (num_cbufs || ish->nir->num_uniforms)235num_cbufs++;236237if (num_system_values || kernel_input_size)238num_cbufs++;239240assert(stage < ARRAY_SIZE(cache_id_for_stage));241enum iris_program_cache_id cache_id = cache_id_for_stage[stage];242243/* Upload our newly read shader to the in-memory program cache and244* return it to the caller.245*/246struct iris_compiled_shader *shader =247iris_upload_shader(screen, ish, NULL, uploader,248cache_id, key_size, prog_key, assembly,249prog_data, so_decls, system_values,250num_system_values, kernel_input_size, num_cbufs, &bt);251252free(buffer);253254return shader;255#else256return NULL;257#endif258}259260/**261* Initialize the on-disk shader cache.262*/263void264iris_disk_cache_init(struct iris_screen *screen)265{266#ifdef ENABLE_SHADER_CACHE267if (INTEL_DEBUG & DEBUG_DISK_CACHE_DISABLE_MASK)268return;269270/* array length = print length + nul char + 1 extra to verify it's unused */271char renderer[11];272UNUSED int len =273snprintf(renderer, sizeof(renderer), "iris_%04x", screen->pci_id);274assert(len == sizeof(renderer) - 2);275276const struct build_id_note *note =277build_id_find_nhdr_for_addr(iris_disk_cache_init);278assert(note && build_id_length(note) == 20); /* sha1 */279280const uint8_t *id_sha1 = build_id_data(note);281assert(id_sha1);282283char timestamp[41];284_mesa_sha1_format(timestamp, id_sha1);285286const uint64_t driver_flags =287brw_get_compiler_config_value(screen->compiler);288screen->disk_cache = disk_cache_create(renderer, timestamp, driver_flags);289#endif290}291292293