zink: handle shader key variants that have nonseamless cubemaps

this is just the program-based handling, which means finding the right
variant and/or creating new ones based on matching a 32bit mask indicating
which textures must be rewritten

Reviewed-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15536>
This commit is contained in:
Mike Blumenkrantz 2022-03-21 14:48:19 -04:00 committed by Marge Bot
parent a06b0e0d21
commit 5b2d0cca17
3 changed files with 56 additions and 40 deletions

View File

@ -69,16 +69,20 @@ debug_describe_zink_compute_program(char *buf, const struct zink_compute_program
static bool
shader_key_matches(const struct zink_shader_module *zm, const struct zink_shader_key *key, unsigned num_uniforms)
{
if (zm->key_size != key->size || zm->num_uniforms != num_uniforms)
if (zm->key_size != key->size || zm->num_uniforms != num_uniforms || zm->has_nonseamless != !!key->base.nonseamless_cube_mask)
return false;
const uint32_t nonseamless_size = zm->has_nonseamless ? sizeof(uint32_t) : 0;
return !memcmp(zm->key, key, zm->key_size) &&
(!num_uniforms || !memcmp(zm->key + zm->key_size, key->base.inlined_uniform_values, zm->num_uniforms * sizeof(uint32_t)));
(!nonseamless_size || !memcmp(zm->key + zm->key_size, &key->base.nonseamless_cube_mask, nonseamless_size)) &&
(!num_uniforms || !memcmp(zm->key + zm->key_size + nonseamless_size,
key->base.inlined_uniform_values, zm->num_uniforms * sizeof(uint32_t)));
}
static uint32_t
shader_module_hash(const struct zink_shader_module *zm)
{
unsigned key_size = zm->key_size + zm->num_uniforms * sizeof(uint32_t);
const uint32_t nonseamless_size = zm->has_nonseamless ? sizeof(uint32_t) : 0;
unsigned key_size = zm->key_size + nonseamless_size + zm->num_uniforms * sizeof(uint32_t);
return _mesa_hash_data(zm->key, key_size);
}
@ -91,7 +95,7 @@ get_shader_module_for_stage(struct zink_context *ctx, struct zink_screen *screen
enum pipe_shader_type pstage = pipe_shader_type_from_mesa(stage);
VkShaderModule mod;
struct zink_shader_module *zm = NULL;
unsigned inline_size = 0;
unsigned inline_size = 0, nonseamless_size = 0;
struct zink_shader_key *key = &state->shader_keys.key[pstage];
if (ctx && zs->nir->info.num_inlinable_uniforms &&
@ -101,9 +105,11 @@ get_shader_module_for_stage(struct zink_context *ctx, struct zink_screen *screen
else
key->inline_uniforms = false;
}
if (key->base.nonseamless_cube_mask)
nonseamless_size = sizeof(uint32_t);
struct zink_shader_module *iter, *next;
LIST_FOR_EACH_ENTRY_SAFE(iter, next, &prog->shader_cache[pstage][!!inline_size], list) {
LIST_FOR_EACH_ENTRY_SAFE(iter, next, &prog->shader_cache[pstage][!!nonseamless_size][!!inline_size], list) {
if (!shader_key_matches(iter, key, inline_size))
continue;
list_delinit(&iter->list);
@ -112,7 +118,7 @@ get_shader_module_for_stage(struct zink_context *ctx, struct zink_screen *screen
}
if (!zm) {
zm = malloc(sizeof(struct zink_shader_module) + key->size + inline_size * sizeof(uint32_t));
zm = malloc(sizeof(struct zink_shader_module) + key->size + nonseamless_size + inline_size * sizeof(uint32_t));
if (!zm) {
return NULL;
}
@ -137,17 +143,22 @@ get_shader_module_for_stage(struct zink_context *ctx, struct zink_screen *screen
zm->key_size = 0;
memset(zm->key, 0, key->size);
}
if (nonseamless_size) {
/* nonseamless mask gets added to base key if it exists */
memcpy(zm->key + key->size, &key->base.nonseamless_cube_mask, nonseamless_size);
}
zm->has_nonseamless = !!nonseamless_size;
if (inline_size)
memcpy(zm->key + key->size, key->base.inlined_uniform_values, inline_size * sizeof(uint32_t));
memcpy(zm->key + key->size + nonseamless_size, key->base.inlined_uniform_values, inline_size * sizeof(uint32_t));
if (zs->is_generated)
zm->hash = zink_get_tcs_key(ctx)->patch_vertices;
else
zm->hash = shader_module_hash(zm);
zm->default_variant = !inline_size && list_is_empty(&prog->shader_cache[pstage][0]);
zm->default_variant = !inline_size && list_is_empty(&prog->shader_cache[pstage][0][0]);
if (inline_size)
prog->inlined_variant_count[pstage]++;
}
list_add(&zm->list, &prog->shader_cache[pstage][!!inline_size]);
list_add(&zm->list, &prog->shader_cache[pstage][!!nonseamless_size][!!inline_size]);
return zm;
}
@ -258,19 +269,6 @@ zink_update_gfx_program(struct zink_context *ctx, struct zink_gfx_program *prog)
update_gfx_shader_modules(ctx, zink_screen(ctx->base.screen), prog, ctx->dirty_shader_stages & prog->stages_present, &ctx->gfx_pipeline_state);
}
static bool
uniforms_match(const struct zink_shader_module *zm, uint32_t *uniforms, unsigned num_uniforms)
{
assert(zm->num_uniforms == num_uniforms);
return !memcmp(zm->key, uniforms, zm->num_uniforms * sizeof(uint32_t));
}
static uint32_t
cs_module_hash(const struct zink_shader_module *zm)
{
return _mesa_hash_data(zm->key, zm->num_uniforms * sizeof(uint32_t));
}
static void
update_cs_shader_module(struct zink_context *ctx, struct zink_compute_program *comp)
{
@ -278,7 +276,7 @@ update_cs_shader_module(struct zink_context *ctx, struct zink_compute_program *c
struct zink_shader *zs = comp->shader;
VkShaderModule mod;
struct zink_shader_module *zm = NULL;
unsigned inline_size = 0;
unsigned inline_size = 0, nonseamless_size = 0;
struct zink_shader_key *key = &ctx->compute_pipeline_state.key;
if (ctx && zs->nir->info.num_inlinable_uniforms &&
@ -288,11 +286,13 @@ update_cs_shader_module(struct zink_context *ctx, struct zink_compute_program *c
else
key->inline_uniforms = false;
}
if (key->base.nonseamless_cube_mask)
nonseamless_size = sizeof(uint32_t);
if (inline_size) {
if (inline_size || nonseamless_size) {
struct zink_shader_module *iter, *next;
LIST_FOR_EACH_ENTRY_SAFE(iter, next, &comp->shader_cache, list) {
if (!uniforms_match(iter, key->base.inlined_uniform_values, inline_size))
LIST_FOR_EACH_ENTRY_SAFE(iter, next, &comp->shader_cache[!!nonseamless_size], list) {
if (!shader_key_matches(iter, key, inline_size))
continue;
list_delinit(&iter->list);
zm = iter;
@ -303,7 +303,7 @@ update_cs_shader_module(struct zink_context *ctx, struct zink_compute_program *c
}
if (!zm) {
zm = malloc(sizeof(struct zink_shader_module) + inline_size * sizeof(uint32_t));
zm = malloc(sizeof(struct zink_shader_module) + nonseamless_size + inline_size * sizeof(uint32_t));
if (!zm) {
return;
}
@ -316,14 +316,19 @@ update_cs_shader_module(struct zink_context *ctx, struct zink_compute_program *c
list_inithead(&zm->list);
zm->num_uniforms = inline_size;
zm->key_size = 0;
assert(inline_size);
memcpy(zm->key, key->base.inlined_uniform_values, inline_size * sizeof(uint32_t));
zm->hash = cs_module_hash(zm);
zm->has_nonseamless = !!nonseamless_size;
assert(nonseamless_size || inline_size);
if (nonseamless_size)
memcpy(zm->key, &key->base.nonseamless_cube_mask, nonseamless_size);
if (inline_size)
memcpy(zm->key + nonseamless_size, key->base.inlined_uniform_values, inline_size * sizeof(uint32_t));
zm->hash = shader_module_hash(zm);
zm->default_variant = false;
comp->inlined_variant_count++;
if (inline_size)
comp->inlined_variant_count++;
}
if (zm->num_uniforms)
list_add(&zm->list, &comp->shader_cache);
if (zm->num_uniforms || nonseamless_size)
list_add(&zm->list, &comp->shader_cache[!!nonseamless_size]);
if (comp->curr == zm)
return;
ctx->compute_pipeline_state.final_hash ^= ctx->compute_pipeline_state.module_hash;
@ -417,8 +422,10 @@ zink_create_gfx_program(struct zink_context *ctx,
pipe_reference_init(&prog->base.reference, 1);
for (int i = 0; i < ZINK_SHADER_COUNT; ++i) {
list_inithead(&prog->shader_cache[i][0]);
list_inithead(&prog->shader_cache[i][1]);
list_inithead(&prog->shader_cache[i][0][0]);
list_inithead(&prog->shader_cache[i][0][1]);
list_inithead(&prog->shader_cache[i][1][0]);
list_inithead(&prog->shader_cache[i][1][1]);
if (stages[i]) {
prog->shaders[i] = stages[i];
prog->stages_present |= BITFIELD_BIT(i);
@ -530,7 +537,8 @@ zink_create_compute_program(struct zink_context *ctx, struct zink_shader *shader
assert(comp->module);
comp->module->shader = zink_shader_compile(screen, shader, shader->nir, NULL);
assert(comp->module->shader);
list_inithead(&comp->shader_cache);
list_inithead(&comp->shader_cache[0]);
list_inithead(&comp->shader_cache[1]);
comp->pipelines = _mesa_hash_table_create(NULL, NULL,
equals_compute_pipeline_state);
@ -666,8 +674,10 @@ zink_destroy_gfx_program(struct zink_context *ctx,
_mesa_set_remove_key(prog->shaders[i]->programs, prog);
prog->shaders[i] = NULL;
}
destroy_shader_cache(screen, &prog->shader_cache[i][0]);
destroy_shader_cache(screen, &prog->shader_cache[i][1]);
destroy_shader_cache(screen, &prog->shader_cache[i][0][0]);
destroy_shader_cache(screen, &prog->shader_cache[i][0][1]);
destroy_shader_cache(screen, &prog->shader_cache[i][1][0]);
destroy_shader_cache(screen, &prog->shader_cache[i][1][1]);
ralloc_free(prog->nir[i]);
}
@ -709,6 +719,8 @@ zink_destroy_compute_program(struct zink_context *ctx,
if (comp->shader)
_mesa_set_remove_key(comp->shader->programs, comp);
destroy_shader_cache(screen, &comp->shader_cache[0]);
destroy_shader_cache(screen, &comp->shader_cache[1]);
hash_table_foreach(comp->pipelines, entry) {
struct compute_pipeline_cache_entry *pc_entry = entry->data;
@ -899,6 +911,8 @@ bind_stage(struct zink_context *ctx, enum pipe_shader_type stage,
ctx->compute_pipeline_state.module_hash = ctx->curr_compute->curr->hash;
ctx->compute_pipeline_state.module = ctx->curr_compute->curr->shader;
ctx->compute_pipeline_state.final_hash ^= ctx->compute_pipeline_state.module_hash;
if (ctx->compute_pipeline_state.key.base.nonseamless_cube_mask)
ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_COMPUTE);
} else if (!shader)
ctx->curr_compute = NULL;
ctx->compute_stage = shader;

View File

@ -68,6 +68,7 @@ struct zink_shader_module {
VkShaderModule shader;
uint32_t hash;
bool default_variant;
bool has_nonseamless;
uint8_t num_uniforms;
uint8_t key_size;
uint8_t key[0]; /* | key | uniforms | */
@ -104,7 +105,7 @@ struct zink_gfx_program {
struct zink_shader *last_vertex_stage;
struct list_head shader_cache[ZINK_SHADER_COUNT][2]; //normal, inline uniforms
struct list_head shader_cache[ZINK_SHADER_COUNT][2][2]; //normal, nonseamless cubes, inline uniforms
unsigned inlined_variant_count[ZINK_SHADER_COUNT];
struct zink_shader *shaders[ZINK_SHADER_COUNT];
@ -119,7 +120,7 @@ struct zink_compute_program {
struct zink_shader_module *curr;
struct zink_shader_module *module; //base
struct list_head shader_cache; //inline uniforms
struct list_head shader_cache[2]; //nonseamless cubes, inline uniforms
unsigned inlined_variant_count;
struct zink_shader *shader;

View File

@ -68,6 +68,7 @@ struct zink_tcs_key {
};
struct zink_shader_key_base {
uint32_t nonseamless_cube_mask;
uint32_t inlined_uniform_values[MAX_INLINABLE_UNIFORMS];
};