Path: blob/21.2-virgl/src/intel/vulkan/anv_pipeline_cache.c
4547 views
/*1* Copyright © 2015 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 (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS20* IN THE SOFTWARE.21*/2223#include "util/blob.h"24#include "util/hash_table.h"25#include "util/debug.h"26#include "util/disk_cache.h"27#include "util/mesa-sha1.h"28#include "nir/nir_serialize.h"29#include "anv_private.h"30#include "nir/nir_xfb_info.h"31#include "vulkan/util/vk_util.h"3233struct anv_shader_bin *34anv_shader_bin_create(struct anv_device *device,35gl_shader_stage stage,36const void *key_data, uint32_t key_size,37const void *kernel_data, uint32_t kernel_size,38const struct brw_stage_prog_data *prog_data_in,39uint32_t prog_data_size,40const struct brw_compile_stats *stats, uint32_t num_stats,41const nir_xfb_info *xfb_info_in,42const struct anv_pipeline_bind_map *bind_map)43{44VK_MULTIALLOC(ma);45VK_MULTIALLOC_DECL(&ma, struct anv_shader_bin, shader, 1);46VK_MULTIALLOC_DECL_SIZE(&ma, struct anv_shader_bin_key, key,47sizeof(*key) + key_size);48VK_MULTIALLOC_DECL_SIZE(&ma, struct brw_stage_prog_data, prog_data,49prog_data_size);50VK_MULTIALLOC_DECL(&ma, struct brw_shader_reloc, prog_data_relocs,51prog_data_in->num_relocs);52VK_MULTIALLOC_DECL(&ma, uint32_t, prog_data_param, prog_data_in->nr_params);5354VK_MULTIALLOC_DECL_SIZE(&ma, nir_xfb_info, xfb_info,55xfb_info_in == NULL ? 0 :56nir_xfb_info_size(xfb_info_in->output_count));5758VK_MULTIALLOC_DECL(&ma, struct anv_pipeline_binding, surface_to_descriptor,59bind_map->surface_count);60VK_MULTIALLOC_DECL(&ma, struct anv_pipeline_binding, sampler_to_descriptor,61bind_map->sampler_count);6263if (!vk_multialloc_alloc(&ma, &device->vk.alloc,64VK_SYSTEM_ALLOCATION_SCOPE_DEVICE))65return NULL;6667shader->ref_cnt = 1;6869shader->stage = stage;7071key->size = key_size;72memcpy(key->data, key_data, key_size);73shader->key = key;7475shader->kernel =76anv_state_pool_alloc(&device->instruction_state_pool, kernel_size, 64);77memcpy(shader->kernel.map, kernel_data, kernel_size);78shader->kernel_size = kernel_size;7980uint64_t shader_data_addr = INSTRUCTION_STATE_POOL_MIN_ADDRESS +81shader->kernel.offset +82prog_data_in->const_data_offset;8384int rv_count = 0;85struct brw_shader_reloc_value reloc_values[5];86reloc_values[rv_count++] = (struct brw_shader_reloc_value) {87.id = BRW_SHADER_RELOC_CONST_DATA_ADDR_LOW,88.value = shader_data_addr,89};90reloc_values[rv_count++] = (struct brw_shader_reloc_value) {91.id = BRW_SHADER_RELOC_CONST_DATA_ADDR_HIGH,92.value = shader_data_addr >> 32,93};94reloc_values[rv_count++] = (struct brw_shader_reloc_value) {95.id = BRW_SHADER_RELOC_SHADER_START_OFFSET,96.value = shader->kernel.offset,97};98if (brw_shader_stage_is_bindless(stage)) {99const struct brw_bs_prog_data *bs_prog_data =100brw_bs_prog_data_const(prog_data_in);101uint64_t resume_sbt_addr = INSTRUCTION_STATE_POOL_MIN_ADDRESS +102shader->kernel.offset +103bs_prog_data->resume_sbt_offset;104reloc_values[rv_count++] = (struct brw_shader_reloc_value) {105.id = BRW_SHADER_RELOC_RESUME_SBT_ADDR_LOW,106.value = resume_sbt_addr,107};108reloc_values[rv_count++] = (struct brw_shader_reloc_value) {109.id = BRW_SHADER_RELOC_RESUME_SBT_ADDR_HIGH,110.value = resume_sbt_addr >> 32,111};112}113114brw_write_shader_relocs(&device->info, shader->kernel.map, prog_data_in,115reloc_values, rv_count);116117memcpy(prog_data, prog_data_in, prog_data_size);118typed_memcpy(prog_data_relocs, prog_data_in->relocs,119prog_data_in->num_relocs);120prog_data->relocs = prog_data_relocs;121memset(prog_data_param, 0,122prog_data->nr_params * sizeof(*prog_data_param));123prog_data->param = prog_data_param;124shader->prog_data = prog_data;125shader->prog_data_size = prog_data_size;126127assert(num_stats <= ARRAY_SIZE(shader->stats));128typed_memcpy(shader->stats, stats, num_stats);129shader->num_stats = num_stats;130131if (xfb_info_in) {132*xfb_info = *xfb_info_in;133typed_memcpy(xfb_info->outputs, xfb_info_in->outputs,134xfb_info_in->output_count);135shader->xfb_info = xfb_info;136} else {137shader->xfb_info = NULL;138}139140shader->bind_map = *bind_map;141typed_memcpy(surface_to_descriptor, bind_map->surface_to_descriptor,142bind_map->surface_count);143shader->bind_map.surface_to_descriptor = surface_to_descriptor;144typed_memcpy(sampler_to_descriptor, bind_map->sampler_to_descriptor,145bind_map->sampler_count);146shader->bind_map.sampler_to_descriptor = sampler_to_descriptor;147148return shader;149}150151void152anv_shader_bin_destroy(struct anv_device *device,153struct anv_shader_bin *shader)154{155assert(shader->ref_cnt == 0);156anv_state_pool_free(&device->instruction_state_pool, shader->kernel);157vk_free(&device->vk.alloc, shader);158}159160static bool161anv_shader_bin_write_to_blob(const struct anv_shader_bin *shader,162struct blob *blob)163{164blob_write_uint32(blob, shader->stage);165166blob_write_uint32(blob, shader->key->size);167blob_write_bytes(blob, shader->key->data, shader->key->size);168169blob_write_uint32(blob, shader->kernel_size);170blob_write_bytes(blob, shader->kernel.map, shader->kernel_size);171172blob_write_uint32(blob, shader->prog_data_size);173blob_write_bytes(blob, shader->prog_data, shader->prog_data_size);174blob_write_bytes(blob, shader->prog_data->relocs,175shader->prog_data->num_relocs *176sizeof(shader->prog_data->relocs[0]));177178blob_write_uint32(blob, shader->num_stats);179blob_write_bytes(blob, shader->stats,180shader->num_stats * sizeof(shader->stats[0]));181182if (shader->xfb_info) {183uint32_t xfb_info_size =184nir_xfb_info_size(shader->xfb_info->output_count);185blob_write_uint32(blob, xfb_info_size);186blob_write_bytes(blob, shader->xfb_info, xfb_info_size);187} else {188blob_write_uint32(blob, 0);189}190191blob_write_bytes(blob, shader->bind_map.surface_sha1,192sizeof(shader->bind_map.surface_sha1));193blob_write_bytes(blob, shader->bind_map.sampler_sha1,194sizeof(shader->bind_map.sampler_sha1));195blob_write_bytes(blob, shader->bind_map.push_sha1,196sizeof(shader->bind_map.push_sha1));197blob_write_uint32(blob, shader->bind_map.surface_count);198blob_write_uint32(blob, shader->bind_map.sampler_count);199blob_write_bytes(blob, shader->bind_map.surface_to_descriptor,200shader->bind_map.surface_count *201sizeof(*shader->bind_map.surface_to_descriptor));202blob_write_bytes(blob, shader->bind_map.sampler_to_descriptor,203shader->bind_map.sampler_count *204sizeof(*shader->bind_map.sampler_to_descriptor));205blob_write_bytes(blob, shader->bind_map.push_ranges,206sizeof(shader->bind_map.push_ranges));207208return !blob->out_of_memory;209}210211static struct anv_shader_bin *212anv_shader_bin_create_from_blob(struct anv_device *device,213struct blob_reader *blob)214{215gl_shader_stage stage = blob_read_uint32(blob);216217uint32_t key_size = blob_read_uint32(blob);218const void *key_data = blob_read_bytes(blob, key_size);219220uint32_t kernel_size = blob_read_uint32(blob);221const void *kernel_data = blob_read_bytes(blob, kernel_size);222223uint32_t prog_data_size = blob_read_uint32(blob);224const void *prog_data_bytes = blob_read_bytes(blob, prog_data_size);225if (blob->overrun)226return NULL;227228union brw_any_prog_data prog_data;229memcpy(&prog_data, prog_data_bytes,230MIN2(sizeof(prog_data), prog_data_size));231prog_data.base.relocs =232blob_read_bytes(blob, prog_data.base.num_relocs *233sizeof(prog_data.base.relocs[0]));234235uint32_t num_stats = blob_read_uint32(blob);236const struct brw_compile_stats *stats =237blob_read_bytes(blob, num_stats * sizeof(stats[0]));238239const nir_xfb_info *xfb_info = NULL;240uint32_t xfb_size = blob_read_uint32(blob);241if (xfb_size)242xfb_info = blob_read_bytes(blob, xfb_size);243244struct anv_pipeline_bind_map bind_map;245blob_copy_bytes(blob, bind_map.surface_sha1, sizeof(bind_map.surface_sha1));246blob_copy_bytes(blob, bind_map.sampler_sha1, sizeof(bind_map.sampler_sha1));247blob_copy_bytes(blob, bind_map.push_sha1, sizeof(bind_map.push_sha1));248bind_map.surface_count = blob_read_uint32(blob);249bind_map.sampler_count = blob_read_uint32(blob);250bind_map.surface_to_descriptor = (void *)251blob_read_bytes(blob, bind_map.surface_count *252sizeof(*bind_map.surface_to_descriptor));253bind_map.sampler_to_descriptor = (void *)254blob_read_bytes(blob, bind_map.sampler_count *255sizeof(*bind_map.sampler_to_descriptor));256blob_copy_bytes(blob, bind_map.push_ranges, sizeof(bind_map.push_ranges));257258if (blob->overrun)259return NULL;260261return anv_shader_bin_create(device, stage,262key_data, key_size,263kernel_data, kernel_size,264&prog_data.base, prog_data_size,265stats, num_stats, xfb_info, &bind_map);266}267268/* Remaining work:269*270* - Compact binding table layout so it's tight and not dependent on271* descriptor set layout.272*273* - Review prog_data struct for size and cacheability: struct274* brw_stage_prog_data has binding_table which uses a lot of uint32_t for 8275* bit quantities etc; use bit fields for all bools, eg dual_src_blend.276*/277278static uint32_t279shader_bin_key_hash_func(const void *void_key)280{281const struct anv_shader_bin_key *key = void_key;282return _mesa_hash_data(key->data, key->size);283}284285static bool286shader_bin_key_compare_func(const void *void_a, const void *void_b)287{288const struct anv_shader_bin_key *a = void_a, *b = void_b;289if (a->size != b->size)290return false;291292return memcmp(a->data, b->data, a->size) == 0;293}294295static uint32_t296sha1_hash_func(const void *sha1)297{298return _mesa_hash_data(sha1, 20);299}300301static bool302sha1_compare_func(const void *sha1_a, const void *sha1_b)303{304return memcmp(sha1_a, sha1_b, 20) == 0;305}306307void308anv_pipeline_cache_init(struct anv_pipeline_cache *cache,309struct anv_device *device,310bool cache_enabled,311bool external_sync)312{313vk_object_base_init(&device->vk, &cache->base,314VK_OBJECT_TYPE_PIPELINE_CACHE);315cache->device = device;316cache->external_sync = external_sync;317pthread_mutex_init(&cache->mutex, NULL);318319if (cache_enabled) {320cache->cache = _mesa_hash_table_create(NULL, shader_bin_key_hash_func,321shader_bin_key_compare_func);322cache->nir_cache = _mesa_hash_table_create(NULL, sha1_hash_func,323sha1_compare_func);324} else {325cache->cache = NULL;326cache->nir_cache = NULL;327}328}329330void331anv_pipeline_cache_finish(struct anv_pipeline_cache *cache)332{333pthread_mutex_destroy(&cache->mutex);334335if (cache->cache) {336/* This is a bit unfortunate. In order to keep things from randomly337* going away, the shader cache has to hold a reference to all shader338* binaries it contains. We unref them when we destroy the cache.339*/340hash_table_foreach(cache->cache, entry)341anv_shader_bin_unref(cache->device, entry->data);342343_mesa_hash_table_destroy(cache->cache, NULL);344}345346if (cache->nir_cache) {347hash_table_foreach(cache->nir_cache, entry)348ralloc_free(entry->data);349350_mesa_hash_table_destroy(cache->nir_cache, NULL);351}352353vk_object_base_finish(&cache->base);354}355356static struct anv_shader_bin *357anv_pipeline_cache_search_locked(struct anv_pipeline_cache *cache,358const void *key_data, uint32_t key_size)359{360uint32_t vla[1 + DIV_ROUND_UP(key_size, sizeof(uint32_t))];361struct anv_shader_bin_key *key = (void *)vla;362key->size = key_size;363memcpy(key->data, key_data, key_size);364365struct hash_entry *entry = _mesa_hash_table_search(cache->cache, key);366if (entry)367return entry->data;368else369return NULL;370}371372static inline void373anv_cache_lock(struct anv_pipeline_cache *cache)374{375if (!cache->external_sync)376pthread_mutex_lock(&cache->mutex);377}378379static inline void380anv_cache_unlock(struct anv_pipeline_cache *cache)381{382if (!cache->external_sync)383pthread_mutex_unlock(&cache->mutex);384}385386struct anv_shader_bin *387anv_pipeline_cache_search(struct anv_pipeline_cache *cache,388const void *key_data, uint32_t key_size)389{390if (!cache->cache)391return NULL;392393anv_cache_lock(cache);394395struct anv_shader_bin *shader =396anv_pipeline_cache_search_locked(cache, key_data, key_size);397398anv_cache_unlock(cache);399400/* We increment refcount before handing it to the caller */401if (shader)402anv_shader_bin_ref(shader);403404return shader;405}406407static void408anv_pipeline_cache_add_shader_bin(struct anv_pipeline_cache *cache,409struct anv_shader_bin *bin)410{411if (!cache->cache)412return;413414anv_cache_lock(cache);415416struct hash_entry *entry = _mesa_hash_table_search(cache->cache, bin->key);417if (entry == NULL) {418/* Take a reference for the cache */419anv_shader_bin_ref(bin);420_mesa_hash_table_insert(cache->cache, bin->key, bin);421}422423anv_cache_unlock(cache);424}425426static struct anv_shader_bin *427anv_pipeline_cache_add_shader_locked(struct anv_pipeline_cache *cache,428gl_shader_stage stage,429const void *key_data, uint32_t key_size,430const void *kernel_data,431uint32_t kernel_size,432const struct brw_stage_prog_data *prog_data,433uint32_t prog_data_size,434const struct brw_compile_stats *stats,435uint32_t num_stats,436const nir_xfb_info *xfb_info,437const struct anv_pipeline_bind_map *bind_map)438{439struct anv_shader_bin *shader =440anv_pipeline_cache_search_locked(cache, key_data, key_size);441if (shader)442return shader;443444struct anv_shader_bin *bin =445anv_shader_bin_create(cache->device, stage,446key_data, key_size,447kernel_data, kernel_size,448prog_data, prog_data_size,449stats, num_stats, xfb_info, bind_map);450if (!bin)451return NULL;452453_mesa_hash_table_insert(cache->cache, bin->key, bin);454455return bin;456}457458struct anv_shader_bin *459anv_pipeline_cache_upload_kernel(struct anv_pipeline_cache *cache,460gl_shader_stage stage,461const void *key_data, uint32_t key_size,462const void *kernel_data, uint32_t kernel_size,463const struct brw_stage_prog_data *prog_data,464uint32_t prog_data_size,465const struct brw_compile_stats *stats,466uint32_t num_stats,467const nir_xfb_info *xfb_info,468const struct anv_pipeline_bind_map *bind_map)469{470if (cache->cache) {471anv_cache_lock(cache);472473struct anv_shader_bin *bin =474anv_pipeline_cache_add_shader_locked(cache, stage, key_data, key_size,475kernel_data, kernel_size,476prog_data, prog_data_size,477stats, num_stats,478xfb_info, bind_map);479480anv_cache_unlock(cache);481482/* We increment refcount before handing it to the caller */483if (bin)484anv_shader_bin_ref(bin);485486return bin;487} else {488/* In this case, we're not caching it so the caller owns it entirely */489return anv_shader_bin_create(cache->device, stage,490key_data, key_size,491kernel_data, kernel_size,492prog_data, prog_data_size,493stats, num_stats,494xfb_info, bind_map);495}496}497498static void499anv_pipeline_cache_load(struct anv_pipeline_cache *cache,500const void *data, size_t size)501{502struct anv_device *device = cache->device;503struct anv_physical_device *pdevice = device->physical;504505if (cache->cache == NULL)506return;507508struct blob_reader blob;509blob_reader_init(&blob, data, size);510511struct vk_pipeline_cache_header header;512blob_copy_bytes(&blob, &header, sizeof(header));513uint32_t count = blob_read_uint32(&blob);514if (blob.overrun)515return;516517if (header.header_size < sizeof(header))518return;519if (header.header_version != VK_PIPELINE_CACHE_HEADER_VERSION_ONE)520return;521if (header.vendor_id != 0x8086)522return;523if (header.device_id != device->info.chipset_id)524return;525if (memcmp(header.uuid, pdevice->pipeline_cache_uuid, VK_UUID_SIZE) != 0)526return;527528for (uint32_t i = 0; i < count; i++) {529struct anv_shader_bin *bin =530anv_shader_bin_create_from_blob(device, &blob);531if (!bin)532break;533_mesa_hash_table_insert(cache->cache, bin->key, bin);534}535}536537VkResult anv_CreatePipelineCache(538VkDevice _device,539const VkPipelineCacheCreateInfo* pCreateInfo,540const VkAllocationCallbacks* pAllocator,541VkPipelineCache* pPipelineCache)542{543ANV_FROM_HANDLE(anv_device, device, _device);544struct anv_pipeline_cache *cache;545546assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO);547548cache = vk_alloc2(&device->vk.alloc, pAllocator,549sizeof(*cache), 8,550VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);551if (cache == NULL)552return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);553554anv_pipeline_cache_init(cache, device,555device->physical->instance->pipeline_cache_enabled,556pCreateInfo->flags & VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT);557558if (pCreateInfo->initialDataSize > 0)559anv_pipeline_cache_load(cache,560pCreateInfo->pInitialData,561pCreateInfo->initialDataSize);562563*pPipelineCache = anv_pipeline_cache_to_handle(cache);564565return VK_SUCCESS;566}567568void anv_DestroyPipelineCache(569VkDevice _device,570VkPipelineCache _cache,571const VkAllocationCallbacks* pAllocator)572{573ANV_FROM_HANDLE(anv_device, device, _device);574ANV_FROM_HANDLE(anv_pipeline_cache, cache, _cache);575576if (!cache)577return;578579anv_pipeline_cache_finish(cache);580581vk_free2(&device->vk.alloc, pAllocator, cache);582}583584VkResult anv_GetPipelineCacheData(585VkDevice _device,586VkPipelineCache _cache,587size_t* pDataSize,588void* pData)589{590ANV_FROM_HANDLE(anv_device, device, _device);591ANV_FROM_HANDLE(anv_pipeline_cache, cache, _cache);592593struct blob blob;594if (pData) {595blob_init_fixed(&blob, pData, *pDataSize);596} else {597blob_init_fixed(&blob, NULL, SIZE_MAX);598}599600struct vk_pipeline_cache_header header = {601.header_size = sizeof(struct vk_pipeline_cache_header),602.header_version = VK_PIPELINE_CACHE_HEADER_VERSION_ONE,603.vendor_id = 0x8086,604.device_id = device->info.chipset_id,605};606memcpy(header.uuid, device->physical->pipeline_cache_uuid, VK_UUID_SIZE);607blob_write_bytes(&blob, &header, sizeof(header));608609uint32_t count = 0;610intptr_t count_offset = blob_reserve_uint32(&blob);611if (count_offset < 0) {612*pDataSize = 0;613blob_finish(&blob);614return VK_INCOMPLETE;615}616617VkResult result = VK_SUCCESS;618if (cache->cache) {619hash_table_foreach(cache->cache, entry) {620struct anv_shader_bin *shader = entry->data;621622size_t save_size = blob.size;623if (!anv_shader_bin_write_to_blob(shader, &blob)) {624/* If it fails reset to the previous size and bail */625blob.size = save_size;626result = VK_INCOMPLETE;627break;628}629630count++;631}632}633634blob_overwrite_uint32(&blob, count_offset, count);635636*pDataSize = blob.size;637638blob_finish(&blob);639640return result;641}642643VkResult anv_MergePipelineCaches(644VkDevice _device,645VkPipelineCache destCache,646uint32_t srcCacheCount,647const VkPipelineCache* pSrcCaches)648{649ANV_FROM_HANDLE(anv_pipeline_cache, dst, destCache);650651if (!dst->cache)652return VK_SUCCESS;653654for (uint32_t i = 0; i < srcCacheCount; i++) {655ANV_FROM_HANDLE(anv_pipeline_cache, src, pSrcCaches[i]);656if (!src->cache)657continue;658659hash_table_foreach(src->cache, entry) {660struct anv_shader_bin *bin = entry->data;661assert(bin);662663if (_mesa_hash_table_search(dst->cache, bin->key))664continue;665666anv_shader_bin_ref(bin);667_mesa_hash_table_insert(dst->cache, bin->key, bin);668}669}670671return VK_SUCCESS;672}673674struct anv_shader_bin *675anv_device_search_for_kernel(struct anv_device *device,676struct anv_pipeline_cache *cache,677const void *key_data, uint32_t key_size,678bool *user_cache_hit)679{680struct anv_shader_bin *bin;681682*user_cache_hit = false;683684if (cache) {685bin = anv_pipeline_cache_search(cache, key_data, key_size);686if (bin) {687*user_cache_hit = cache != &device->default_pipeline_cache;688return bin;689}690}691692#ifdef ENABLE_SHADER_CACHE693struct disk_cache *disk_cache = device->physical->disk_cache;694if (disk_cache && device->physical->instance->pipeline_cache_enabled) {695cache_key cache_key;696disk_cache_compute_key(disk_cache, key_data, key_size, cache_key);697698size_t buffer_size;699uint8_t *buffer = disk_cache_get(disk_cache, cache_key, &buffer_size);700if (buffer) {701struct blob_reader blob;702blob_reader_init(&blob, buffer, buffer_size);703bin = anv_shader_bin_create_from_blob(device, &blob);704free(buffer);705706if (bin) {707if (cache)708anv_pipeline_cache_add_shader_bin(cache, bin);709return bin;710}711}712}713#endif714715return NULL;716}717718struct anv_shader_bin *719anv_device_upload_kernel(struct anv_device *device,720struct anv_pipeline_cache *cache,721gl_shader_stage stage,722const void *key_data, uint32_t key_size,723const void *kernel_data, uint32_t kernel_size,724const struct brw_stage_prog_data *prog_data,725uint32_t prog_data_size,726const struct brw_compile_stats *stats,727uint32_t num_stats,728const nir_xfb_info *xfb_info,729const struct anv_pipeline_bind_map *bind_map)730{731struct anv_shader_bin *bin;732if (cache) {733bin = anv_pipeline_cache_upload_kernel(cache, stage, key_data, key_size,734kernel_data, kernel_size,735prog_data, prog_data_size,736stats, num_stats,737xfb_info, bind_map);738} else {739bin = anv_shader_bin_create(device, stage, key_data, key_size,740kernel_data, kernel_size,741prog_data, prog_data_size,742stats, num_stats,743xfb_info, bind_map);744}745746if (bin == NULL)747return NULL;748749#ifdef ENABLE_SHADER_CACHE750struct disk_cache *disk_cache = device->physical->disk_cache;751if (disk_cache) {752struct blob binary;753blob_init(&binary);754if (anv_shader_bin_write_to_blob(bin, &binary)) {755cache_key cache_key;756disk_cache_compute_key(disk_cache, key_data, key_size, cache_key);757758disk_cache_put(disk_cache, cache_key, binary.data, binary.size, NULL);759}760761blob_finish(&binary);762}763#endif764765return bin;766}767768struct serialized_nir {769unsigned char sha1_key[20];770size_t size;771char data[0];772};773774struct nir_shader *775anv_device_search_for_nir(struct anv_device *device,776struct anv_pipeline_cache *cache,777const nir_shader_compiler_options *nir_options,778unsigned char sha1_key[20],779void *mem_ctx)780{781if (cache && cache->nir_cache) {782const struct serialized_nir *snir = NULL;783784anv_cache_lock(cache);785struct hash_entry *entry =786_mesa_hash_table_search(cache->nir_cache, sha1_key);787if (entry)788snir = entry->data;789anv_cache_unlock(cache);790791if (snir) {792struct blob_reader blob;793blob_reader_init(&blob, snir->data, snir->size);794795nir_shader *nir = nir_deserialize(mem_ctx, nir_options, &blob);796if (blob.overrun) {797ralloc_free(nir);798} else {799return nir;800}801}802}803804return NULL;805}806807void808anv_device_upload_nir(struct anv_device *device,809struct anv_pipeline_cache *cache,810const struct nir_shader *nir,811unsigned char sha1_key[20])812{813if (cache && cache->nir_cache) {814anv_cache_lock(cache);815struct hash_entry *entry =816_mesa_hash_table_search(cache->nir_cache, sha1_key);817anv_cache_unlock(cache);818if (entry)819return;820821struct blob blob;822blob_init(&blob);823824nir_serialize(&blob, nir, false);825if (blob.out_of_memory) {826blob_finish(&blob);827return;828}829830anv_cache_lock(cache);831/* Because ralloc isn't thread-safe, we have to do all this inside the832* lock. We could unlock for the big memcpy but it's probably not worth833* the hassle.834*/835entry = _mesa_hash_table_search(cache->nir_cache, sha1_key);836if (entry) {837blob_finish(&blob);838anv_cache_unlock(cache);839return;840}841842struct serialized_nir *snir =843ralloc_size(cache->nir_cache, sizeof(*snir) + blob.size);844memcpy(snir->sha1_key, sha1_key, 20);845snir->size = blob.size;846memcpy(snir->data, blob.data, blob.size);847848blob_finish(&blob);849850_mesa_hash_table_insert(cache->nir_cache, snir->sha1_key, snir);851852anv_cache_unlock(cache);853}854}855856857