Path: blob/21.2-virgl/src/gallium/drivers/iris/iris_program_cache.c
4565 views
/*1* Copyright © 2017 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_program_cache.c24*25* The in-memory program cache. This is basically a hash table mapping26* API-specified shaders and a state key to a compiled variant. It also27* takes care of uploading shader assembly into a BO for use on the GPU.28*/2930#include <stdio.h>31#include <errno.h>32#include "pipe/p_defines.h"33#include "pipe/p_state.h"34#include "pipe/p_context.h"35#include "pipe/p_screen.h"36#include "util/u_atomic.h"37#include "util/u_upload_mgr.h"38#include "compiler/nir/nir.h"39#include "compiler/nir/nir_builder.h"40#include "intel/common/intel_disasm.h"41#include "intel/compiler/brw_compiler.h"42#include "intel/compiler/brw_eu.h"43#include "intel/compiler/brw_nir.h"44#include "iris_context.h"45#include "iris_resource.h"4647struct keybox {48uint16_t size;49enum iris_program_cache_id cache_id;50uint8_t data[0];51};5253static struct keybox *54make_keybox(void *mem_ctx,55enum iris_program_cache_id cache_id,56const void *key,57uint32_t key_size)58{59struct keybox *keybox =60ralloc_size(mem_ctx, sizeof(struct keybox) + key_size);6162keybox->cache_id = cache_id;63keybox->size = key_size;64memcpy(keybox->data, key, key_size);6566return keybox;67}6869static uint32_t70keybox_hash(const void *void_key)71{72const struct keybox *key = void_key;73return _mesa_hash_data(&key->cache_id, key->size + sizeof(key->cache_id));74}7576static bool77keybox_equals(const void *void_a, const void *void_b)78{79const struct keybox *a = void_a, *b = void_b;80if (a->size != b->size)81return false;8283return memcmp(a->data, b->data, a->size) == 0;84}8586struct iris_compiled_shader *87iris_find_cached_shader(struct iris_context *ice,88enum iris_program_cache_id cache_id,89uint32_t key_size,90const void *key)91{92struct keybox *keybox = make_keybox(NULL, cache_id, key, key_size);93struct hash_entry *entry =94_mesa_hash_table_search(ice->shaders.cache, keybox);9596ralloc_free(keybox);9798return entry ? entry->data : NULL;99}100101void102iris_delete_shader_variant(struct iris_compiled_shader *shader)103{104pipe_resource_reference(&shader->assembly.res, NULL);105ralloc_free(shader);106}107108struct iris_compiled_shader *109iris_upload_shader(struct iris_screen *screen,110struct iris_uncompiled_shader *ish,111struct hash_table *driver_shaders,112struct u_upload_mgr *uploader,113enum iris_program_cache_id cache_id,114uint32_t key_size,115const void *key,116const void *assembly,117struct brw_stage_prog_data *prog_data,118uint32_t *streamout,119enum brw_param_builtin *system_values,120unsigned num_system_values,121unsigned kernel_input_size,122unsigned num_cbufs,123const struct iris_binding_table *bt)124{125const struct intel_device_info *devinfo = &screen->devinfo;126127void *mem_ctx = ish ? NULL : (void *) driver_shaders;128struct iris_compiled_shader *shader =129rzalloc_size(mem_ctx, sizeof(struct iris_compiled_shader) +130screen->vtbl.derived_program_state_size(cache_id));131132pipe_reference_init(&shader->ref, 1);133134shader->assembly.res = NULL;135u_upload_alloc(uploader, 0, prog_data->program_size, 64,136&shader->assembly.offset, &shader->assembly.res,137&shader->map);138memcpy(shader->map, assembly, prog_data->program_size);139140struct iris_resource *res = (void *) shader->assembly.res;141uint64_t shader_data_addr = res->bo->gtt_offset +142shader->assembly.offset +143prog_data->const_data_offset;144145struct brw_shader_reloc_value reloc_values[] = {146{147.id = BRW_SHADER_RELOC_CONST_DATA_ADDR_LOW,148.value = shader_data_addr,149},150{151.id = BRW_SHADER_RELOC_CONST_DATA_ADDR_HIGH,152.value = shader_data_addr >> 32,153},154};155brw_write_shader_relocs(&screen->devinfo, shader->map, prog_data,156reloc_values, ARRAY_SIZE(reloc_values));157158shader->prog_data = prog_data;159shader->streamout = streamout;160shader->system_values = system_values;161shader->num_system_values = num_system_values;162shader->kernel_input_size = kernel_input_size;163shader->num_cbufs = num_cbufs;164shader->bt = *bt;165166ralloc_steal(shader, shader->prog_data);167ralloc_steal(shader->prog_data, (void *)prog_data->relocs);168ralloc_steal(shader->prog_data, prog_data->param);169ralloc_steal(shader->prog_data, prog_data->pull_param);170ralloc_steal(shader, shader->streamout);171ralloc_steal(shader, shader->system_values);172173/* Store the 3DSTATE shader packets and other derived state. */174screen->vtbl.store_derived_program_state(devinfo, cache_id, shader);175176if (ish) {177assert(key_size <= sizeof(union iris_any_prog_key));178memcpy(&shader->key, key, key_size);179180simple_mtx_lock(&ish->lock);181182/* While unlikely, it's possible that another thread concurrently183* compiled the same variant. Make sure no one beat us to it; if184* they did, return the existing one and discard our new one.185*/186list_for_each_entry(struct iris_compiled_shader, existing,187&ish->variants, link) {188if (memcmp(&existing->key, key, key_size) == 0) {189iris_delete_shader_variant(shader);190simple_mtx_unlock(&ish->lock);191return existing;192}193}194195/* Append our new variant to the shader's variant list. */196list_addtail(&shader->link, &ish->variants);197198simple_mtx_unlock(&ish->lock);199} else {200struct keybox *keybox = make_keybox(shader, cache_id, key, key_size);201_mesa_hash_table_insert(driver_shaders, keybox, shader);202}203204return shader;205}206207bool208iris_blorp_lookup_shader(struct blorp_batch *blorp_batch,209const void *key, uint32_t key_size,210uint32_t *kernel_out, void *prog_data_out)211{212struct blorp_context *blorp = blorp_batch->blorp;213struct iris_context *ice = blorp->driver_ctx;214struct iris_batch *batch = blorp_batch->driver_batch;215struct iris_compiled_shader *shader =216iris_find_cached_shader(ice, IRIS_CACHE_BLORP, key_size, key);217218if (!shader)219return false;220221struct iris_bo *bo = iris_resource_bo(shader->assembly.res);222*kernel_out =223iris_bo_offset_from_base_address(bo) + shader->assembly.offset;224*((void **) prog_data_out) = shader->prog_data;225226iris_use_pinned_bo(batch, bo, false, IRIS_DOMAIN_NONE);227228return true;229}230231bool232iris_blorp_upload_shader(struct blorp_batch *blorp_batch, uint32_t stage,233const void *key, uint32_t key_size,234const void *kernel, UNUSED uint32_t kernel_size,235const struct brw_stage_prog_data *prog_data_templ,236UNUSED uint32_t prog_data_size,237uint32_t *kernel_out, void *prog_data_out)238{239struct blorp_context *blorp = blorp_batch->blorp;240struct iris_context *ice = blorp->driver_ctx;241struct iris_batch *batch = blorp_batch->driver_batch;242struct iris_screen *screen = batch->screen;243244void *prog_data = ralloc_size(NULL, prog_data_size);245memcpy(prog_data, prog_data_templ, prog_data_size);246247struct iris_binding_table bt;248memset(&bt, 0, sizeof(bt));249250struct iris_compiled_shader *shader =251iris_upload_shader(screen, NULL, ice->shaders.cache,252ice->shaders.uploader_driver,253IRIS_CACHE_BLORP, key_size, key, kernel,254prog_data, NULL, NULL, 0, 0, 0, &bt);255256struct iris_bo *bo = iris_resource_bo(shader->assembly.res);257*kernel_out =258iris_bo_offset_from_base_address(bo) + shader->assembly.offset;259*((void **) prog_data_out) = shader->prog_data;260261iris_use_pinned_bo(batch, bo, false, IRIS_DOMAIN_NONE);262263return true;264}265266void267iris_init_program_cache(struct iris_context *ice)268{269ice->shaders.cache =270_mesa_hash_table_create(ice, keybox_hash, keybox_equals);271272ice->shaders.uploader_driver =273u_upload_create(&ice->ctx, 16384, PIPE_BIND_CUSTOM, PIPE_USAGE_IMMUTABLE,274IRIS_RESOURCE_FLAG_SHADER_MEMZONE |275IRIS_RESOURCE_FLAG_DEVICE_MEM);276ice->shaders.uploader_unsync =277u_upload_create(&ice->ctx, 16384, PIPE_BIND_CUSTOM, PIPE_USAGE_IMMUTABLE,278IRIS_RESOURCE_FLAG_SHADER_MEMZONE |279IRIS_RESOURCE_FLAG_DEVICE_MEM);280}281282void283iris_destroy_program_cache(struct iris_context *ice)284{285for (int i = 0; i < MESA_SHADER_STAGES; i++) {286iris_shader_variant_reference(&ice->shaders.prog[i], NULL);287}288iris_shader_variant_reference(&ice->shaders.last_vue_shader, NULL);289290hash_table_foreach(ice->shaders.cache, entry) {291struct iris_compiled_shader *shader = entry->data;292iris_delete_shader_variant(shader);293}294295u_upload_destroy(ice->shaders.uploader_driver);296u_upload_destroy(ice->shaders.uploader_unsync);297298ralloc_free(ice->shaders.cache);299}300301302