iris: Add the variant to the list as early as possible
I tried to find a way to break this into some smaller commits, but everything is very intertwined. :( When searching the variants list in the iris_uncompiled_shader, add the new variant if it is not found. This will be necessary for threaded shader compilation. This conceptually simple change had a bunch of fallout. Much of this was at least conceptually borrowed from radeonsi. - Other threads might find a variant in the list before the variant has been compiled. To accomdate this, add a fence. Each thread will wait on the fence in the variant when searching the list. - A variant in the list may fail compilation. To accomodate this, add a flag. All paths will examine iris_compiled_shader::compilation_failed before trying to use the variant. - The race condition between multiple threads trying to create the same variant at the same time is handled *before* both thread spend the effort to compile the shader. The means that iris_upload_shader cannot change shaders on the caller, so it does not need to return anything. v2: Change "found" parameter of find_or_add_variant to "added." This inverts the values returned, and it probably makes uses of the returned value more easily understood. Always set the value in the called function. Suggested by Ken. v3: Move shader->compilation_failed check to avoid shader != NULL test. Rearrange some logic and add a comment in iris_update_compiled_tcs. Suggested by Ken. Don't call find_or_add_variant in iris_create_shader_state. See https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11229#note_1000843 for more details. Noticed by Ken. Reviewed-by: Kenneth Graunke <kenneth@whitecape.org> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11229>
This commit is contained in:
parent
0e48b1a99d
commit
2024d47048
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue