X-Git-Url: https://git.libre-soc.org/?p=mesa.git;a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Firis%2Firis_program_cache.c;h=5bee13f2d429b46b50d6e1de9a00dfc05025164d;hp=9fad14a28477e7e67cf07828ac49688170af75c1;hb=bc2c5f9a4b696564fe99170d1e80fa33e989e6af;hpb=f8796079dab4a3d6fb9ea034b93fd38de53fbe1f diff --git a/src/gallium/drivers/iris/iris_program_cache.c b/src/gallium/drivers/iris/iris_program_cache.c index 9fad14a2847..5bee13f2d42 100644 --- a/src/gallium/drivers/iris/iris_program_cache.c +++ b/src/gallium/drivers/iris/iris_program_cache.c @@ -38,6 +38,7 @@ #include "util/u_upload_mgr.h" #include "compiler/nir/nir.h" #include "compiler/nir/nir_builder.h" +#include "intel/common/gen_disasm.h" #include "intel/compiler/brw_compiler.h" #include "intel/compiler/brw_eu.h" #include "intel/compiler/brw_nir.h" @@ -45,29 +46,11 @@ #include "iris_resource.h" struct keybox { - uint8_t size; + uint16_t size; enum iris_program_cache_id cache_id; uint8_t data[0]; }; -static uint32_t -key_size_for_cache(enum iris_program_cache_id cache_id) -{ - static const unsigned key_sizes[] = { - [IRIS_CACHE_VS] = sizeof(struct brw_vs_prog_key), - [IRIS_CACHE_TCS] = sizeof(struct brw_tcs_prog_key), - [IRIS_CACHE_TES] = sizeof(struct brw_tes_prog_key), - [IRIS_CACHE_GS] = sizeof(struct brw_gs_prog_key), - [IRIS_CACHE_FS] = sizeof(struct brw_wm_prog_key), - [IRIS_CACHE_CS] = sizeof(struct brw_cs_prog_key), - }; - - /* BLORP keys aren't all the same size. */ - assert(cache_id != IRIS_CACHE_BLORP); - - return key_sizes[cache_id]; -} - static struct keybox * make_keybox(void *mem_ctx, enum iris_program_cache_id cache_id, @@ -101,56 +84,13 @@ keybox_equals(const void *void_a, const void *void_b) return memcmp(a->data, b->data, a->size) == 0; } -static uint64_t -dirty_flag_for_cache(enum iris_program_cache_id cache_id) -{ - assert(cache_id <= MESA_SHADER_STAGES); - - // XXX: ugly... - // XXX: move this flagging out to a higher level, allow comparison of - // XXX: new and old programs to decide what bits to twiddle - // XXX: CLIP: toggle if barycentric modes has any NONPERSPECTIVE or not - if (cache_id == IRIS_CACHE_FS) - return IRIS_DIRTY_WM | IRIS_DIRTY_FS | IRIS_DIRTY_CLIP | IRIS_DIRTY_SBE; - if (cache_id == IRIS_CACHE_VS) - return IRIS_DIRTY_VS | IRIS_DIRTY_VF_SGVS; - - /* For compute, prog_data->threads needs to be uploaded as constants. */ - if (cache_id == IRIS_CACHE_CS) - return IRIS_DIRTY_CS | IRIS_DIRTY_CONSTANTS_CS; - - return IRIS_DIRTY_VS << cache_id | IRIS_DIRTY_BINDINGS_VS << cache_id; -} - -static unsigned -get_program_string_id(enum iris_program_cache_id cache_id, const void *key) -{ - switch (cache_id) { - case IRIS_CACHE_VS: - return ((struct brw_vs_prog_key *) key)->program_string_id; - case IRIS_CACHE_TCS: - return ((struct brw_tcs_prog_key *) key)->program_string_id; - case IRIS_CACHE_TES: - return ((struct brw_tes_prog_key *) key)->program_string_id; - case IRIS_CACHE_GS: - return ((struct brw_gs_prog_key *) key)->program_string_id; - case IRIS_CACHE_CS: - return ((struct brw_cs_prog_key *) key)->program_string_id; - case IRIS_CACHE_FS: - return ((struct brw_wm_prog_key *) key)->program_string_id; - default: - unreachable("no program string id for this kind of program"); - } -} - -static struct iris_compiled_shader * +struct iris_compiled_shader * iris_find_cached_shader(struct iris_context *ice, enum iris_program_cache_id cache_id, - const void *key, - uint32_t key_size) + uint32_t key_size, + const void *key) { - struct keybox *keybox = - make_keybox(ice->shaders.cache, cache_id, key, key_size); + struct keybox *keybox = make_keybox(NULL, cache_id, key, key_size); struct hash_entry *entry = _mesa_hash_table_search(ice->shaders.cache, keybox); @@ -159,43 +99,6 @@ iris_find_cached_shader(struct iris_context *ice, return entry ? entry->data : NULL; } -/** - * Looks for a program in the cache and binds it. - * - * If no program was found, returns false and leaves the binding alone. - */ -bool -iris_bind_cached_shader(struct iris_context *ice, - enum iris_program_cache_id cache_id, - const void *key) -{ - unsigned key_size = key_size_for_cache(cache_id); - struct iris_compiled_shader *shader = - iris_find_cached_shader(ice, cache_id, key, key_size); - - if (!shader) - return false; - - // XXX: why memcmp? - if (!ice->shaders.prog[cache_id] || - memcmp(shader, ice->shaders.prog[cache_id], sizeof(*shader)) != 0) { - ice->shaders.prog[cache_id] = shader; - ice->state.dirty |= dirty_flag_for_cache(cache_id); - } - - return true; -} - -void -iris_unbind_shader(struct iris_context *ice, - enum iris_program_cache_id cache_id) -{ - if (ice->shaders.prog[cache_id]) { - ice->shaders.prog[cache_id] = NULL; - ice->state.dirty |= dirty_flag_for_cache(cache_id); - } -} - const void * iris_find_previous_compile(const struct iris_context *ice, enum iris_program_cache_id cache_id, @@ -203,8 +106,9 @@ iris_find_previous_compile(const struct iris_context *ice, { hash_table_foreach(ice->shaders.cache, entry) { const struct keybox *keybox = entry->key; + const struct brw_base_prog_key *key = (const void *)keybox->data; if (keybox->cache_id == cache_id && - get_program_string_id(cache_id, keybox->data) == program_string_id) { + key->program_string_id == program_string_id) { return keybox->data; } } @@ -212,6 +116,59 @@ iris_find_previous_compile(const struct iris_context *ice, return NULL; } +void +iris_delete_shader_variants(struct iris_context *ice, + struct iris_uncompiled_shader *ish) +{ + struct hash_table *cache = ice->shaders.cache; + gl_shader_stage stage = ish->nir->info.stage; + enum iris_program_cache_id cache_id = stage; + + hash_table_foreach(cache, entry) { + const struct keybox *keybox = entry->key; + const struct brw_base_prog_key *key = (const void *)keybox->data; + + if (keybox->cache_id == cache_id && + key->program_string_id == ish->program_id) { + struct iris_compiled_shader *shader = entry->data; + + _mesa_hash_table_remove(cache, entry); + + /* Shader variants may still be bound in the context even after + * the API-facing shader has been deleted. In particular, a draw + * may not have triggered iris_update_compiled_shaders() yet. In + * that case, we may be referring to that shader's VUE map, stream + * output settings, and so on. We also like to compare the old and + * new shader programs when swapping them out to flag dirty state. + * + * So, it's hazardous to delete a bound shader variant. We avoid + * doing so, choosing to instead move "deleted" shader variants to + * a list, deferring the actual deletion until they're not bound. + * + * For simplicity, we always move deleted variants to the list, + * even if we could delete them immediately. We'll then process + * the list, catching both these variants and any others. + */ + list_addtail(&shader->link, &ice->shaders.deleted_variants[stage]); + } + } + + /* Process any pending deferred variant deletions. */ + list_for_each_entry_safe(struct iris_compiled_shader, shader, + &ice->shaders.deleted_variants[stage], link) { + /* If the shader is still bound, defer deletion. */ + if (ice->shaders.prog[stage] == shader) + continue; + + list_del(&shader->link); + + /* Actually delete the variant. */ + pipe_resource_reference(&shader->assembly.res, NULL); + ralloc_free(shader); + } +} + + /** * Look for an existing entry in the cache that has identical assembly code. * @@ -233,21 +190,25 @@ find_existing_assembly(struct hash_table *cache, return NULL; } -static struct iris_compiled_shader * +struct iris_compiled_shader * iris_upload_shader(struct iris_context *ice, enum iris_program_cache_id cache_id, uint32_t key_size, const void *key, const void *assembly, struct brw_stage_prog_data *prog_data, - uint32_t *streamout) + uint32_t *streamout, + enum brw_param_builtin *system_values, + unsigned num_system_values, + unsigned kernel_input_size, + unsigned num_cbufs, + const struct iris_binding_table *bt) { - struct iris_screen *screen = (void *) ice->ctx.screen; - struct gen_device_info *devinfo = &screen->devinfo; struct hash_table *cache = ice->shaders.cache; + struct iris_screen *screen = (struct iris_screen *)ice->ctx.screen; struct iris_compiled_shader *shader = rzalloc_size(cache, sizeof(struct iris_compiled_shader) + - ice->vtbl.derived_program_state_size(cache_id)); + screen->vtbl.derived_program_state_size(cache_id)); const struct iris_compiled_shader *existing = find_existing_assembly(cache, assembly, prog_data->program_size); @@ -269,46 +230,31 @@ iris_upload_shader(struct iris_context *ice, memcpy(shader->map, assembly, prog_data->program_size); } + list_inithead(&shader->link); + shader->prog_data = prog_data; shader->streamout = streamout; + shader->system_values = system_values; + shader->num_system_values = num_system_values; + shader->kernel_input_size = kernel_input_size; + shader->num_cbufs = num_cbufs; + shader->bt = *bt; ralloc_steal(shader, shader->prog_data); ralloc_steal(shader->prog_data, prog_data->param); ralloc_steal(shader->prog_data, prog_data->pull_param); ralloc_steal(shader, shader->streamout); + ralloc_steal(shader, shader->system_values); /* Store the 3DSTATE shader packets and other derived state. */ - ice->vtbl.store_derived_program_state(devinfo, cache_id, shader); + screen->vtbl.store_derived_program_state(ice, cache_id, shader); - struct keybox *keybox = make_keybox(cache, cache_id, key, key_size); + struct keybox *keybox = make_keybox(shader, cache_id, key, key_size); _mesa_hash_table_insert(ice->shaders.cache, keybox, shader); return shader; } -/** - * Upload a new shader to the program cache, and bind it for use. - * - * \param prog_data must be ralloc'd and will be stolen. - */ -void -iris_upload_and_bind_shader(struct iris_context *ice, - enum iris_program_cache_id cache_id, - const void *key, - const void *assembly, - struct brw_stage_prog_data *prog_data, - uint32_t *streamout) -{ - assert(cache_id != IRIS_CACHE_BLORP); - - struct iris_compiled_shader *shader = - iris_upload_shader(ice, cache_id, key_size_for_cache(cache_id), key, - assembly, prog_data, streamout); - - ice->shaders.prog[cache_id] = shader; - ice->state.dirty |= dirty_flag_for_cache(cache_id); -} - bool iris_blorp_lookup_shader(struct blorp_batch *blorp_batch, const void *key, uint32_t key_size, @@ -318,7 +264,7 @@ iris_blorp_lookup_shader(struct blorp_batch *blorp_batch, struct iris_context *ice = blorp->driver_ctx; struct iris_batch *batch = blorp_batch->driver_batch; struct iris_compiled_shader *shader = - iris_find_cached_shader(ice, IRIS_CACHE_BLORP, key, key_size); + iris_find_cached_shader(ice, IRIS_CACHE_BLORP, key_size, key); if (!shader) return false; @@ -328,13 +274,13 @@ iris_blorp_lookup_shader(struct blorp_batch *blorp_batch, iris_bo_offset_from_base_address(bo) + shader->assembly.offset; *((void **) prog_data_out) = shader->prog_data; - iris_use_pinned_bo(batch, bo, false); + iris_use_pinned_bo(batch, bo, false, IRIS_DOMAIN_NONE); return true; } bool -iris_blorp_upload_shader(struct blorp_batch *blorp_batch, +iris_blorp_upload_shader(struct blorp_batch *blorp_batch, uint32_t stage, const void *key, uint32_t key_size, const void *kernel, UNUSED uint32_t kernel_size, const struct brw_stage_prog_data *prog_data_templ, @@ -348,16 +294,19 @@ iris_blorp_upload_shader(struct blorp_batch *blorp_batch, void *prog_data = ralloc_size(NULL, prog_data_size); memcpy(prog_data, prog_data_templ, prog_data_size); + struct iris_binding_table bt; + memset(&bt, 0, sizeof(bt)); + struct iris_compiled_shader *shader = iris_upload_shader(ice, IRIS_CACHE_BLORP, key_size, key, kernel, - prog_data, NULL); + prog_data, NULL, NULL, 0, 0, 0, &bt); struct iris_bo *bo = iris_resource_bo(shader->assembly.res); *kernel_out = iris_bo_offset_from_base_address(bo) + shader->assembly.offset; *((void **) prog_data_out) = shader->prog_data; - iris_use_pinned_bo(batch, bo, false); + iris_use_pinned_bo(batch, bo, false, IRIS_DOMAIN_NONE); return true; } @@ -371,6 +320,9 @@ iris_init_program_cache(struct iris_context *ice) ice->shaders.uploader = u_upload_create(&ice->ctx, 16384, PIPE_BIND_CUSTOM, PIPE_USAGE_IMMUTABLE, IRIS_RESOURCE_FLAG_SHADER_MEMZONE); + + for (int i = 0; i < MESA_SHADER_STAGES; i++) + list_inithead(&ice->shaders.deleted_variants[i]); } void @@ -378,6 +330,11 @@ iris_destroy_program_cache(struct iris_context *ice) { for (int i = 0; i < MESA_SHADER_STAGES; i++) { ice->shaders.prog[i] = NULL; + + list_for_each_entry_safe(struct iris_compiled_shader, shader, + &ice->shaders.deleted_variants[i], link) { + pipe_resource_reference(&shader->assembly.res, NULL); + } } hash_table_foreach(ice->shaders.cache, entry) { @@ -409,7 +366,6 @@ iris_print_program_cache(struct iris_context *ice) const struct keybox *keybox = entry->key; struct iris_compiled_shader *shader = entry->data; fprintf(stderr, "%s:\n", cache_name(keybox->cache_id)); - brw_disassemble(devinfo, shader->map, 0, - shader->prog_data->program_size, stderr); + gen_disassemble(devinfo, shader->map, 0, stderr); } }