diff --git a/src/gallium/drivers/iris/iris_context.h b/src/gallium/drivers/iris/iris_context.h index c9dd66b988b..626db8c2f17 100644 --- a/src/gallium/drivers/iris/iris_context.h +++ b/src/gallium/drivers/iris/iris_context.h @@ -460,6 +460,18 @@ struct iris_compiled_shader { /** Key for this variant (but not for BLORP programs) */ union iris_any_prog_key key; + /** + * Is the variant fully compiled and ready? + * + * Variants are added to \c iris_uncompiled_shader::variants before + * compilation actually occurs. This signals that compilation has + * completed. + */ + struct util_queue_fence ready; + + /** Variant is ready, but compilation failed. */ + bool compilation_failed; + /** Reference to the uploaded assembly. */ struct iris_state_ref assembly; @@ -925,10 +937,11 @@ void iris_disk_cache_store(struct disk_cache *cache, const struct iris_compiled_shader *shader, const void *prog_key, uint32_t prog_key_size); -struct iris_compiled_shader * +bool iris_disk_cache_retrieve(struct iris_screen *screen, struct u_upload_mgr *uploader, struct iris_uncompiled_shader *ish, + struct iris_compiled_shader *shader, const void *prog_key, uint32_t prog_key_size); @@ -947,22 +960,22 @@ struct iris_compiled_shader *iris_create_shader_variant(const struct iris_screen uint32_t key_size, const void *key); -struct iris_compiled_shader *iris_upload_shader(struct iris_screen *screen, - struct iris_uncompiled_shader *, - struct iris_compiled_shader *, - struct hash_table *driver_ht, - struct u_upload_mgr *uploader, - enum iris_program_cache_id, - uint32_t key_size, - const void *key, - const void *assembly, - struct brw_stage_prog_data *, - uint32_t *streamout, - enum brw_param_builtin *sysv, - unsigned num_system_values, - unsigned kernel_input_size, - unsigned num_cbufs, - const struct iris_binding_table *bt); +void iris_upload_shader(struct iris_screen *screen, + struct iris_uncompiled_shader *, + struct iris_compiled_shader *, + struct hash_table *driver_ht, + struct u_upload_mgr *uploader, + enum iris_program_cache_id, + uint32_t key_size, + const void *key, + const void *assembly, + struct brw_stage_prog_data *, + uint32_t *streamout, + enum brw_param_builtin *sysv, + unsigned num_system_values, + unsigned kernel_input_size, + unsigned num_cbufs, + const struct iris_binding_table *bt); void iris_delete_shader_variant(struct iris_compiled_shader *shader); void iris_destroy_shader_state(struct pipe_context *ctx, void *state); diff --git a/src/gallium/drivers/iris/iris_disk_cache.c b/src/gallium/drivers/iris/iris_disk_cache.c index 3be0301b1ef..62313edde31 100644 --- a/src/gallium/drivers/iris/iris_disk_cache.c +++ b/src/gallium/drivers/iris/iris_disk_cache.c @@ -141,10 +141,11 @@ static const enum iris_program_cache_id cache_id_for_stage[] = { * Search for a compiled shader in the disk cache. If found, upload it * to the in-memory program cache so we can use it. */ -struct iris_compiled_shader * +bool iris_disk_cache_retrieve(struct iris_screen *screen, struct u_upload_mgr *uploader, struct iris_uncompiled_shader *ish, + struct iris_compiled_shader *shader, const void *prog_key, uint32_t key_size) { @@ -153,7 +154,7 @@ iris_disk_cache_retrieve(struct iris_screen *screen, gl_shader_stage stage = ish->nir->info.stage; if (!cache) - return NULL; + return false; cache_key cache_key; iris_disk_cache_compute_key(cache, ish, prog_key, key_size, cache_key); @@ -171,7 +172,7 @@ iris_disk_cache_retrieve(struct iris_screen *screen, fprintf(stderr, "%s\n", buffer ? "found" : "missing"); if (!buffer) - return NULL; + return false; const uint32_t prog_data_size = brw_prog_data_size(stage); @@ -241,22 +242,17 @@ iris_disk_cache_retrieve(struct iris_screen *screen, assert(stage < ARRAY_SIZE(cache_id_for_stage)); enum iris_program_cache_id cache_id = cache_id_for_stage[stage]; - /* Upload our newly read shader to the in-memory program cache and - * return it to the caller. - */ - struct iris_compiled_shader *shader = - iris_create_shader_variant(screen, NULL, cache_id, key_size, prog_key); - - shader = iris_upload_shader(screen, ish, shader, NULL, uploader, - cache_id, key_size, prog_key, assembly, - prog_data, so_decls, system_values, - num_system_values, kernel_input_size, num_cbufs, &bt); + /* Upload our newly read shader to the in-memory program cache. */ + iris_upload_shader(screen, ish, shader, NULL, uploader, + cache_id, key_size, prog_key, assembly, + prog_data, so_decls, system_values, + num_system_values, kernel_input_size, num_cbufs, &bt); free(buffer); - return shader; + return true; #else - return NULL; + return false; #endif } diff --git a/src/gallium/drivers/iris/iris_program.c b/src/gallium/drivers/iris/iris_program.c index 0f4c83feaf7..6fae0b5b794 100644 --- a/src/gallium/drivers/iris/iris_program.c +++ b/src/gallium/drivers/iris/iris_program.c @@ -1107,13 +1107,22 @@ last_vue_stage(struct iris_context *ice) return MESA_SHADER_VERTEX; } +/** + * \param added Set to \c true if the variant was added to the list (i.e., a + * variant matching \c key was not found). Set to \c false + * otherwise. + */ static inline struct iris_compiled_shader * -find_variant(const struct iris_screen *screen, - struct iris_uncompiled_shader *ish, - const void *key, unsigned key_size) +find_or_add_variant(const struct iris_screen *screen, + struct iris_uncompiled_shader *ish, + enum iris_program_cache_id cache_id, + const void *key, unsigned key_size, + bool *added) { struct list_head *start = ish->variants.next; + *added = false; + if (screen->precompile) { /* Check the first list entry. There will always be at least one * variant in the list (most likely the precompile variant), and @@ -1123,8 +1132,10 @@ find_variant(const struct iris_screen *screen, struct iris_compiled_shader *first = list_first_entry(&ish->variants, struct iris_compiled_shader, link); - if (memcmp(&first->key, key, key_size) == 0) + if (memcmp(&first->key, key, key_size) == 0) { + util_queue_fence_wait(&first->ready); return first; + } /* Skip this one in the loop below */ start = first->link.next; @@ -1145,7 +1156,20 @@ find_variant(const struct iris_screen *screen, } } - simple_mtx_unlock(&ish->lock); + if (variant == NULL) { + variant = iris_create_shader_variant(screen, NULL, cache_id, + key_size, key); + + /* Append our new variant to the shader's variant list. */ + list_addtail(&variant->link, &ish->variants); + *added = true; + + simple_mtx_unlock(&ish->lock); + } else { + simple_mtx_unlock(&ish->lock); + + util_queue_fence_wait(&variant->ready); + } return variant; } @@ -1153,11 +1177,12 @@ find_variant(const struct iris_screen *screen, /** * Compile a vertex shader, and upload the assembly. */ -static struct iris_compiled_shader * +static void iris_compile_vs(struct iris_screen *screen, struct u_upload_mgr *uploader, struct pipe_debug_callback *dbg, struct iris_uncompiled_shader *ish, + struct iris_compiled_shader *shader, const struct iris_vs_prog_key *key) { const struct brw_compiler *compiler = screen->compiler; @@ -1211,27 +1236,28 @@ iris_compile_vs(struct iris_screen *screen, if (program == NULL) { dbg_printf("Failed to compile vertex shader: %s\n", params.error_str); ralloc_free(mem_ctx); - return NULL; + + shader->compilation_failed = true; + util_queue_fence_signal(&shader->ready); + + return; } + shader->compilation_failed = false; + iris_debug_recompile(screen, dbg, ish, &brw_key.base); uint32_t *so_decls = screen->vtbl.create_so_decl_list(&ish->stream_output, &vue_prog_data->vue_map); - struct iris_compiled_shader *shader = - iris_create_shader_variant(screen, NULL, IRIS_CACHE_VS, sizeof(*key), key); - - shader = iris_upload_shader(screen, ish, shader, NULL, uploader, - IRIS_CACHE_VS, sizeof(*key), key, program, - prog_data, so_decls, system_values, num_system_values, - 0, num_cbufs, &bt); + iris_upload_shader(screen, ish, shader, NULL, uploader, IRIS_CACHE_VS, + sizeof(*key), key, program, prog_data, so_decls, + system_values, num_system_values, 0, num_cbufs, &bt); iris_disk_cache_store(screen->disk_cache, ish, shader, key, sizeof(*key)); ralloc_free(mem_ctx); - return shader; } /** @@ -1252,16 +1278,17 @@ iris_update_compiled_vs(struct iris_context *ice) screen->vtbl.populate_vs_key(ice, &ish->nir->info, last_vue_stage(ice), &key); struct iris_compiled_shader *old = ice->shaders.prog[IRIS_CACHE_VS]; + bool added; struct iris_compiled_shader *shader = - find_variant(screen, ish, &key, sizeof(key)); + find_or_add_variant(screen, ish, IRIS_CACHE_VS, &key, sizeof(key), &added); - if (!shader) { - shader = iris_disk_cache_retrieve(screen, uploader, ish, - &key, sizeof(key)); + if (added && !iris_disk_cache_retrieve(screen, uploader, ish, shader, + &key, sizeof(key))) { + iris_compile_vs(screen, uploader, &ice->dbg, ish, shader, &key); } - if (!shader) - shader = iris_compile_vs(screen, uploader, &ice->dbg, ish, &key); + if (shader->compilation_failed) + shader = NULL; if (old != shader) { iris_shader_variant_reference(&ice->shaders.prog[MESA_SHADER_VERTEX], @@ -1327,12 +1354,13 @@ get_unified_tess_slots(const struct iris_context *ice, /** * Compile a tessellation control shader, and upload the assembly. */ -static struct iris_compiled_shader * +static void iris_compile_tcs(struct iris_screen *screen, struct hash_table *passthrough_ht, struct u_upload_mgr *uploader, struct pipe_debug_callback *dbg, struct iris_uncompiled_shader *ish, + struct iris_compiled_shader *shader, const struct iris_tcs_prog_key *key) { const struct brw_compiler *compiler = screen->compiler; @@ -1407,27 +1435,26 @@ iris_compile_tcs(struct iris_screen *screen, if (program == NULL) { dbg_printf("Failed to compile control shader: %s\n", error_str); ralloc_free(mem_ctx); - return NULL; + + shader->compilation_failed = true; + util_queue_fence_signal(&shader->ready); + + return; } + shader->compilation_failed = false; + iris_debug_recompile(screen, dbg, ish, &brw_key.base); - void *passthrough_mem_ctx = (ish != NULL) ? NULL : passthrough_ht; - - struct iris_compiled_shader *shader = - iris_create_shader_variant(screen, passthrough_mem_ctx, IRIS_CACHE_TCS, - sizeof(*key), key); - - shader = iris_upload_shader(screen, ish, shader, passthrough_ht, uploader, - IRIS_CACHE_TCS, sizeof(*key), key, program, - prog_data, NULL, system_values, num_system_values, - 0, num_cbufs, &bt); + iris_upload_shader(screen, ish, shader, passthrough_ht, uploader, + IRIS_CACHE_TCS, sizeof(*key), key, program, prog_data, + NULL, system_values, num_system_values, 0, num_cbufs, + &bt); if (ish) iris_disk_cache_store(screen->disk_cache, ish, shader, key, sizeof(*key)); ralloc_free(mem_ctx); - return shader; } /** @@ -1462,20 +1489,39 @@ iris_update_compiled_tcs(struct iris_context *ice) screen->vtbl.populate_tcs_key(ice, &key); struct iris_compiled_shader *old = ice->shaders.prog[IRIS_CACHE_TCS]; - struct iris_compiled_shader *shader = - tcs ? find_variant(screen, tcs, &key, sizeof(key)) : - iris_find_cached_shader(ice, IRIS_CACHE_TCS, sizeof(key), &key); + struct iris_compiled_shader *shader; + bool added = false; + + if (tcs != NULL) { + shader = find_or_add_variant(screen, tcs, IRIS_CACHE_TCS, &key, + sizeof(key), &added); + } else { + /* Look for and possibly create a passthrough TCS */ + shader = iris_find_cached_shader(ice, IRIS_CACHE_TCS, sizeof(key), &key); + + + if (shader == NULL) { + shader = iris_create_shader_variant(screen, ice->shaders.cache, + IRIS_CACHE_TCS, sizeof(key), &key); + added = true; + } - if (tcs && !shader) { - shader = iris_disk_cache_retrieve(screen, uploader, tcs, - &key, sizeof(key)); } - if (!shader) { - shader = iris_compile_tcs(screen, ice->shaders.cache, - uploader, &ice->dbg, tcs, &key); + /* If the shader was not found in (whichever cache), call iris_compile_tcs + * if either ish is NULL or the shader could not be found in the disk + * cache. + */ + if (added && + (tcs == NULL || !iris_disk_cache_retrieve(screen, uploader, tcs, shader, + &key, sizeof(key)))) { + iris_compile_tcs(screen, ice->shaders.cache, uploader, &ice->dbg, tcs, + shader, &key); } + if (shader->compilation_failed) + shader = NULL; + if (old != shader) { iris_shader_variant_reference(&ice->shaders.prog[MESA_SHADER_TESS_CTRL], shader); @@ -1492,11 +1538,12 @@ iris_update_compiled_tcs(struct iris_context *ice) /** * Compile a tessellation evaluation shader, and upload the assembly. */ -static struct iris_compiled_shader * +static void iris_compile_tes(struct iris_screen *screen, struct u_upload_mgr *uploader, struct pipe_debug_callback *dbg, struct iris_uncompiled_shader *ish, + struct iris_compiled_shader *shader, const struct iris_tes_prog_key *key) { const struct brw_compiler *compiler = screen->compiler; @@ -1544,27 +1591,28 @@ iris_compile_tes(struct iris_screen *screen, if (program == NULL) { dbg_printf("Failed to compile evaluation shader: %s\n", error_str); ralloc_free(mem_ctx); - return NULL; + + shader->compilation_failed = true; + util_queue_fence_signal(&shader->ready); + + return; } + shader->compilation_failed = false; + iris_debug_recompile(screen, dbg, ish, &brw_key.base); uint32_t *so_decls = screen->vtbl.create_so_decl_list(&ish->stream_output, &vue_prog_data->vue_map); - struct iris_compiled_shader *shader = - iris_create_shader_variant(screen, NULL, IRIS_CACHE_TES, sizeof(*key), key); - - shader = iris_upload_shader(screen, ish, shader, NULL, uploader, - IRIS_CACHE_TES, sizeof(*key), key, program, - prog_data, so_decls, system_values, num_system_values, - 0, num_cbufs, &bt); + iris_upload_shader(screen, ish, shader, NULL, uploader, IRIS_CACHE_TES, + sizeof(*key), key, program, prog_data, so_decls, + system_values, num_system_values, 0, num_cbufs, &bt); iris_disk_cache_store(screen->disk_cache, ish, shader, key, sizeof(*key)); ralloc_free(mem_ctx); - return shader; } /** @@ -1586,16 +1634,17 @@ iris_update_compiled_tes(struct iris_context *ice) screen->vtbl.populate_tes_key(ice, &ish->nir->info, last_vue_stage(ice), &key); struct iris_compiled_shader *old = ice->shaders.prog[IRIS_CACHE_TES]; + bool added; struct iris_compiled_shader *shader = - find_variant(screen, ish, &key, sizeof(key)); + find_or_add_variant(screen, ish, IRIS_CACHE_TES, &key, sizeof(key), &added); - if (!shader) { - shader = iris_disk_cache_retrieve(screen, uploader, ish, - &key, sizeof(key)); + if (added && !iris_disk_cache_retrieve(screen, uploader, ish, shader, + &key, sizeof(key))) { + iris_compile_tes(screen, uploader, &ice->dbg, ish, shader, &key); } - if (!shader) - shader = iris_compile_tes(screen, uploader, &ice->dbg, ish, &key); + if (shader->compilation_failed) + shader = NULL; if (old != shader) { iris_shader_variant_reference(&ice->shaders.prog[MESA_SHADER_TESS_EVAL], @@ -1620,11 +1669,12 @@ iris_update_compiled_tes(struct iris_context *ice) /** * Compile a geometry shader, and upload the assembly. */ -static struct iris_compiled_shader * +static void iris_compile_gs(struct iris_screen *screen, struct u_upload_mgr *uploader, struct pipe_debug_callback *dbg, struct iris_uncompiled_shader *ish, + struct iris_compiled_shader *shader, const struct iris_gs_prog_key *key) { const struct brw_compiler *compiler = screen->compiler; @@ -1672,27 +1722,28 @@ iris_compile_gs(struct iris_screen *screen, if (program == NULL) { dbg_printf("Failed to compile geometry shader: %s\n", error_str); ralloc_free(mem_ctx); - return NULL; + + shader->compilation_failed = true; + util_queue_fence_signal(&shader->ready); + + return; } + shader->compilation_failed = false; + iris_debug_recompile(screen, dbg, ish, &brw_key.base); uint32_t *so_decls = screen->vtbl.create_so_decl_list(&ish->stream_output, &vue_prog_data->vue_map); - struct iris_compiled_shader *shader = - iris_create_shader_variant(screen, NULL, IRIS_CACHE_GS, sizeof(*key), key); - - shader = iris_upload_shader(screen, ish, shader, NULL, uploader, - IRIS_CACHE_GS, sizeof(*key), key, program, - prog_data, so_decls, system_values, num_system_values, - 0, num_cbufs, &bt); + iris_upload_shader(screen, ish, shader, NULL, uploader, IRIS_CACHE_GS, + sizeof(*key), key, program, prog_data, so_decls, + system_values, num_system_values, 0, num_cbufs, &bt); iris_disk_cache_store(screen->disk_cache, ish, shader, key, sizeof(*key)); ralloc_free(mem_ctx); - return shader; } /** @@ -1715,15 +1766,18 @@ iris_update_compiled_gs(struct iris_context *ice) struct iris_gs_prog_key key = { KEY_ID(vue.base) }; screen->vtbl.populate_gs_key(ice, &ish->nir->info, last_vue_stage(ice), &key); - shader = find_variant(screen, ish, &key, sizeof(key)); + bool added; - if (!shader) { - shader = iris_disk_cache_retrieve(screen, uploader, ish, - &key, sizeof(key)); + shader = find_or_add_variant(screen, ish, IRIS_CACHE_GS, &key, + sizeof(key), &added); + + if (added && !iris_disk_cache_retrieve(screen, uploader, ish, shader, + &key, sizeof(key))) { + iris_compile_gs(screen, uploader, &ice->dbg, ish, shader, &key); } - if (!shader) - shader = iris_compile_gs(screen, uploader, &ice->dbg, ish, &key); + if (shader->compilation_failed) + shader = NULL; } if (old != shader) { @@ -1743,11 +1797,12 @@ iris_update_compiled_gs(struct iris_context *ice) /** * Compile a fragment (pixel) shader, and upload the assembly. */ -static struct iris_compiled_shader * +static void iris_compile_fs(struct iris_screen *screen, struct u_upload_mgr *uploader, struct pipe_debug_callback *dbg, struct iris_uncompiled_shader *ish, + struct iris_compiled_shader *shader, const struct iris_fs_prog_key *key, struct brw_vue_map *vue_map) { @@ -1805,23 +1860,24 @@ iris_compile_fs(struct iris_screen *screen, if (program == NULL) { dbg_printf("Failed to compile fragment shader: %s\n", params.error_str); ralloc_free(mem_ctx); - return NULL; + + shader->compilation_failed = true; + util_queue_fence_signal(&shader->ready); + + return; } + shader->compilation_failed = false; + iris_debug_recompile(screen, dbg, ish, &brw_key.base); - struct iris_compiled_shader *shader = - iris_create_shader_variant(screen, NULL, IRIS_CACHE_FS, sizeof(*key), key); - - shader = iris_upload_shader(screen, ish, shader, NULL, uploader, - IRIS_CACHE_FS, sizeof(*key), key, program, - prog_data, NULL, system_values, num_system_values, - 0, num_cbufs, &bt); + iris_upload_shader(screen, ish, shader, NULL, uploader, IRIS_CACHE_FS, + sizeof(*key), key, program, prog_data, NULL, + system_values, num_system_values, 0, num_cbufs, &bt); iris_disk_cache_store(screen->disk_cache, ish, shader, key, sizeof(*key)); ralloc_free(mem_ctx); - return shader; } /** @@ -1847,18 +1903,19 @@ iris_update_compiled_fs(struct iris_context *ice) key.input_slots_valid = last_vue_map->slots_valid; struct iris_compiled_shader *old = ice->shaders.prog[IRIS_CACHE_FS]; + bool added; struct iris_compiled_shader *shader = - find_variant(screen, ish, &key, sizeof(key)); + find_or_add_variant(screen, ish, IRIS_CACHE_FS, &key, + sizeof(key), &added); - if (!shader) { - shader = iris_disk_cache_retrieve(screen, uploader, ish, - &key, sizeof(key)); + if (added && !iris_disk_cache_retrieve(screen, uploader, ish, shader, + &key, sizeof(key))) { + iris_compile_fs(screen, uploader, &ice->dbg, ish, shader, &key, + last_vue_map); } - if (!shader) { - shader = iris_compile_fs(screen, uploader, &ice->dbg, - ish, &key, last_vue_map); - } + if (shader->compilation_failed) + shader = NULL; if (old != shader) { // XXX: only need to flag CLIP if barycentric has NONPERSPECTIVE @@ -2032,11 +2089,12 @@ iris_update_compiled_shaders(struct iris_context *ice) } } -static struct iris_compiled_shader * +static void iris_compile_cs(struct iris_screen *screen, struct u_upload_mgr *uploader, struct pipe_debug_callback *dbg, struct iris_uncompiled_shader *ish, + struct iris_compiled_shader *shader, const struct iris_cs_prog_key *key) { const struct brw_compiler *compiler = screen->compiler; @@ -2073,24 +2131,25 @@ iris_compile_cs(struct iris_screen *screen, const unsigned *program = brw_compile_cs(compiler, mem_ctx, ¶ms); if (program == NULL) { dbg_printf("Failed to compile compute shader: %s\n", params.error_str); - ralloc_free(mem_ctx); - return false; + + shader->compilation_failed = true; + util_queue_fence_signal(&shader->ready); + + return; } + shader->compilation_failed = false; + iris_debug_recompile(screen, dbg, ish, &brw_key.base); - struct iris_compiled_shader *shader = - iris_create_shader_variant(screen, NULL, IRIS_CACHE_CS, sizeof(*key), key); - - shader = iris_upload_shader(screen, ish, shader, NULL, uploader, - IRIS_CACHE_CS, sizeof(*key), key, program, - prog_data, NULL, system_values, num_system_values, - ish->kernel_input_size, num_cbufs, &bt); + iris_upload_shader(screen, ish, shader, NULL, uploader, IRIS_CACHE_CS, + sizeof(*key), key, program, prog_data, NULL, + system_values, num_system_values, ish->kernel_input_size, + num_cbufs, &bt); iris_disk_cache_store(screen->disk_cache, ish, shader, key, sizeof(*key)); ralloc_free(mem_ctx); - return shader; } static void @@ -2106,16 +2165,18 @@ iris_update_compiled_cs(struct iris_context *ice) screen->vtbl.populate_cs_key(ice, &key); struct iris_compiled_shader *old = ice->shaders.prog[IRIS_CACHE_CS]; + bool added; struct iris_compiled_shader *shader = - find_variant(screen, ish, &key, sizeof(key)); + find_or_add_variant(screen, ish, IRIS_CACHE_CS, &key, + sizeof(key), &added); - if (!shader) { - shader = iris_disk_cache_retrieve(screen, uploader, ish, - &key, sizeof(key)); + if (added && !iris_disk_cache_retrieve(screen, uploader, ish, shader, + &key, sizeof(key))) { + iris_compile_cs(screen, uploader, &ice->dbg, ish, shader, &key); } - if (!shader) - shader = iris_compile_cs(screen, uploader, &ice->dbg, ish, &key); + if (shader->compilation_failed) + shader = NULL; if (old != shader) { iris_shader_variant_reference(&ice->shaders.prog[MESA_SHADER_COMPUTE], @@ -2383,8 +2444,14 @@ iris_create_compute_state(struct pipe_context *ctx, if (screen->precompile) { struct iris_cs_prog_key key = { KEY_ID(base) }; - if (!iris_disk_cache_retrieve(screen, uploader, ish, &key, sizeof(key))) - iris_compile_cs(screen, uploader, &ice->dbg, ish, &key); + struct iris_compiled_shader *shader = + iris_create_shader_variant(screen, NULL, IRIS_CACHE_CS, + sizeof(key), &key); + + if (!iris_disk_cache_retrieve(screen, uploader, ish, shader, + &key, sizeof(key))) { + iris_compile_cs(screen, uploader, &ice->dbg, ish, shader, &key); + } } return ish; @@ -2395,28 +2462,28 @@ iris_compile_shader(struct iris_screen *screen, struct u_upload_mgr *uploader, struct pipe_debug_callback *dbg, struct iris_uncompiled_shader *ish, - const void *key) + struct iris_compiled_shader *shader) { switch (ish->nir->info.stage) { case MESA_SHADER_VERTEX: - iris_compile_vs(screen, uploader, dbg, ish, - (const struct iris_vs_prog_key *) key); + iris_compile_vs(screen, uploader, dbg, ish, shader, + &shader->key.vs); break; case MESA_SHADER_TESS_CTRL: - iris_compile_tcs(screen, NULL, uploader, dbg, ish, - (const struct iris_tcs_prog_key *) key); + iris_compile_tcs(screen, NULL, uploader, dbg, ish, shader, + &shader->key.tcs); break; case MESA_SHADER_TESS_EVAL: - iris_compile_tes(screen, uploader, dbg, ish, - (const struct iris_tes_prog_key *) key); + iris_compile_tes(screen, uploader, dbg, ish, shader, + &shader->key.tes); break; case MESA_SHADER_GEOMETRY: - iris_compile_gs(screen, uploader, dbg, ish, - (const struct iris_gs_prog_key *) key); + iris_compile_gs(screen, uploader, dbg, ish, shader, + &shader->key.gs); break; case MESA_SHADER_FRAGMENT: - iris_compile_fs(screen, uploader, dbg, ish, - (const struct iris_fs_prog_key *) key, NULL); + iris_compile_fs(screen, uploader, dbg, ish, shader, + &shader->key.fs, NULL); break; default: @@ -2544,8 +2611,18 @@ iris_create_shader_state(struct pipe_context *ctx, if (screen->precompile) { struct u_upload_mgr *uploader = ice->shaders.uploader_unsync; - if (!iris_disk_cache_retrieve(screen, uploader, ish, &key, key_size)) - iris_compile_shader(screen, uploader, &ice->dbg, ish, &key); + struct iris_compiled_shader *shader = + iris_create_shader_variant(screen, NULL, + (enum iris_program_cache_id) info->stage, + key_size, &key); + + /* Append our new variant to the shader's variant list. */ + list_addtail(&shader->link, &ish->variants); + + if (!iris_disk_cache_retrieve(screen, uploader, ish, shader, + &key, key_size)) { + iris_compile_shader(screen, uploader, &ice->dbg, ish, shader); + } } return ish; diff --git a/src/gallium/drivers/iris/iris_program_cache.c b/src/gallium/drivers/iris/iris_program_cache.c index 235cf99e8ef..bb8795403cb 100644 --- a/src/gallium/drivers/iris/iris_program_cache.c +++ b/src/gallium/drivers/iris/iris_program_cache.c @@ -103,6 +103,7 @@ void iris_delete_shader_variant(struct iris_compiled_shader *shader) { pipe_resource_reference(&shader->assembly.res, NULL); + util_queue_fence_destroy(&shader->ready); ralloc_free(shader); } @@ -134,6 +135,8 @@ iris_create_shader_variant(const struct iris_screen *screen, screen->vtbl.derived_program_state_size(cache_id)); pipe_reference_init(&shader->ref, 1); + util_queue_fence_init(&shader->ready); + util_queue_fence_reset(&shader->ready); if (cache_id != IRIS_CACHE_BLORP) { assert(key_size <= sizeof(union iris_any_prog_key)); @@ -143,7 +146,7 @@ iris_create_shader_variant(const struct iris_screen *screen, return shader; } -struct iris_compiled_shader * +void iris_upload_shader(struct iris_screen *screen, struct iris_uncompiled_shader *ish, struct iris_compiled_shader *shader, @@ -204,32 +207,12 @@ iris_upload_shader(struct iris_screen *screen, /* Store the 3DSTATE shader packets and other derived state. */ screen->vtbl.store_derived_program_state(devinfo, cache_id, shader); - if (ish) { - simple_mtx_lock(&ish->lock); + util_queue_fence_signal(&shader->ready); - /* While unlikely, it's possible that another thread concurrently - * compiled the same variant. Make sure no one beat us to it; if - * they did, return the existing one and discard our new one. - */ - list_for_each_entry(struct iris_compiled_shader, existing, - &ish->variants, link) { - if (memcmp(&existing->key, key, key_size) == 0) { - iris_delete_shader_variant(shader); - simple_mtx_unlock(&ish->lock); - return existing; - } - } - - /* Append our new variant to the shader's variant list. */ - list_addtail(&shader->link, &ish->variants); - - simple_mtx_unlock(&ish->lock); - } else { + if (!ish) { struct keybox *keybox = make_keybox(shader, cache_id, key, key_size); _mesa_hash_table_insert(driver_shaders, keybox, shader); } - - return shader; } bool