mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-26 19:20:08 +01:00
zink: handle switching between primitives
Zink will generate geometry shaders to emulate certain features, however there might be different variants of those depending on the primitive type. This commits adds the logic to generate or bind the correct emulation GS in the case where nothing changes except the primitive type. Reviewed-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com> Reviewed-by: Erik Faye-Lund <erik.faye-lund@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21238>
This commit is contained in:
parent
32107d8b5a
commit
eedbf9046e
3 changed files with 36 additions and 20 deletions
|
|
@ -4646,8 +4646,10 @@ zink_shader_free(struct zink_screen *screen, struct zink_shader *shader)
|
|||
/* only remove generated tcs during parent tes destruction */
|
||||
if (stage == MESA_SHADER_TESS_EVAL && shader->non_fs.generated_tcs)
|
||||
prog->shaders[MESA_SHADER_TESS_CTRL] = NULL;
|
||||
if (stage != MESA_SHADER_FRAGMENT && shader->non_fs.generated_gs)
|
||||
prog->shaders[MESA_SHADER_GEOMETRY] = NULL;
|
||||
for (unsigned int i = 0; i < ARRAY_SIZE(shader->non_fs.generated_gs); i++) {
|
||||
if (stage != MESA_SHADER_FRAGMENT && shader->non_fs.generated_gs[i])
|
||||
prog->shaders[MESA_SHADER_GEOMETRY] = NULL;
|
||||
}
|
||||
zink_gfx_program_reference(screen, &prog, NULL);
|
||||
}
|
||||
if (shader->nir->info.stage == MESA_SHADER_TESS_EVAL &&
|
||||
|
|
@ -4656,11 +4658,13 @@ zink_shader_free(struct zink_screen *screen, struct zink_shader *shader)
|
|||
zink_shader_free(screen, shader->non_fs.generated_tcs);
|
||||
shader->non_fs.generated_tcs = NULL;
|
||||
}
|
||||
if (shader->nir->info.stage != MESA_SHADER_FRAGMENT &&
|
||||
shader->non_fs.generated_gs) {
|
||||
/* automatically destroy generated gs shaders when owner is destroyed */
|
||||
zink_shader_free(screen, shader->non_fs.generated_gs);
|
||||
shader->non_fs.generated_gs = NULL;
|
||||
for (unsigned int i = 0; i < ARRAY_SIZE(shader->non_fs.generated_gs); i++) {
|
||||
if (shader->nir->info.stage != MESA_SHADER_FRAGMENT &&
|
||||
shader->non_fs.generated_gs[i]) {
|
||||
/* automatically destroy generated gs shaders when owner is destroyed */
|
||||
zink_shader_free(screen, shader->non_fs.generated_gs[i]);
|
||||
shader->non_fs.generated_gs[i] = NULL;
|
||||
}
|
||||
}
|
||||
_mesa_set_destroy(shader->programs, NULL);
|
||||
util_queue_fence_wait(&shader->precompile.fence);
|
||||
|
|
|
|||
|
|
@ -1562,6 +1562,22 @@ zink_get_compute_pipeline(struct zink_screen *screen,
|
|||
return state->pipeline;
|
||||
}
|
||||
|
||||
static void
|
||||
bind_gfx_stage(struct zink_context *ctx, gl_shader_stage stage, struct zink_shader *shader);
|
||||
|
||||
static void
|
||||
unbind_generated_gs(struct zink_context *ctx, gl_shader_stage stage, struct zink_shader *shader)
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(shader->non_fs.generated_gs); i++) {
|
||||
if (ctx->gfx_stages[stage]->non_fs.generated_gs[i] &&
|
||||
ctx->gfx_stages[MESA_SHADER_GEOMETRY] ==
|
||||
ctx->gfx_stages[stage]->non_fs.generated_gs[i]) {
|
||||
assert(stage != MESA_SHADER_GEOMETRY); /* let's not keep recursing! */
|
||||
bind_gfx_stage(ctx, MESA_SHADER_GEOMETRY, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bind_gfx_stage(struct zink_context *ctx, gl_shader_stage stage, struct zink_shader *shader)
|
||||
{
|
||||
|
|
@ -1573,15 +1589,10 @@ bind_gfx_stage(struct zink_context *ctx, gl_shader_stage stage, struct zink_shad
|
|||
if (ctx->gfx_stages[stage]) {
|
||||
ctx->gfx_hash ^= ctx->gfx_stages[stage]->hash;
|
||||
|
||||
/* unbind the generated GS */
|
||||
if (stage != MESA_SHADER_FRAGMENT &&
|
||||
ctx->gfx_stages[stage]->non_fs.generated_gs &&
|
||||
ctx->gfx_stages[MESA_SHADER_GEOMETRY] ==
|
||||
ctx->gfx_stages[stage]->non_fs.generated_gs) {
|
||||
assert(stage != MESA_SHADER_GEOMETRY); /* let's not keep recursing! */
|
||||
bind_gfx_stage(ctx, MESA_SHADER_GEOMETRY, NULL);
|
||||
}
|
||||
if (stage != MESA_SHADER_FRAGMENT)
|
||||
unbind_generated_gs(ctx, stage, shader);
|
||||
}
|
||||
|
||||
ctx->gfx_stages[stage] = shader;
|
||||
ctx->gfx_dirty = ctx->gfx_stages[MESA_SHADER_FRAGMENT] && ctx->gfx_stages[MESA_SHADER_VERTEX];
|
||||
ctx->gfx_pipeline_state.modules_changed = true;
|
||||
|
|
@ -2200,10 +2211,11 @@ zink_set_primitive_emulation_keys(struct zink_context *ctx)
|
|||
ctx->gfx_stages[MESA_SHADER_TESS_EVAL] ?
|
||||
MESA_SHADER_TESS_EVAL : MESA_SHADER_VERTEX;
|
||||
|
||||
if (!ctx->gfx_stages[MESA_SHADER_GEOMETRY]) {
|
||||
if (!ctx->gfx_stages[MESA_SHADER_GEOMETRY] ||
|
||||
(ctx->gfx_stages[MESA_SHADER_GEOMETRY]->nir->info.gs.input_primitive != ctx->gfx_pipeline_state.gfx_prim_mode)) {
|
||||
assert(!screen->optimal_keys);
|
||||
|
||||
if (!ctx->gfx_stages[prev_vertex_stage]->non_fs.generated_gs) {
|
||||
if (!ctx->gfx_stages[prev_vertex_stage]->non_fs.generated_gs[ctx->gfx_pipeline_state.gfx_prim_mode]) {
|
||||
nir_shader *nir = nir_create_passthrough_gs(
|
||||
&screen->nir_options,
|
||||
ctx->gfx_stages[prev_vertex_stage]->nir,
|
||||
|
|
@ -2211,12 +2223,12 @@ zink_set_primitive_emulation_keys(struct zink_context *ctx)
|
|||
(lower_line_stipple || lower_line_smooth) ? 2 : 1);
|
||||
|
||||
struct zink_shader *shader = zink_shader_create(screen, nir, NULL);
|
||||
ctx->gfx_stages[prev_vertex_stage]->non_fs.generated_gs = shader;
|
||||
ctx->gfx_stages[prev_vertex_stage]->non_fs.generated_gs[ctx->gfx_pipeline_state.gfx_prim_mode] = shader;
|
||||
shader->non_fs.is_generated = true;
|
||||
}
|
||||
|
||||
bind_gfx_stage(ctx, MESA_SHADER_GEOMETRY,
|
||||
ctx->gfx_stages[prev_vertex_stage]->non_fs.generated_gs);
|
||||
ctx->gfx_stages[prev_vertex_stage]->non_fs.generated_gs[ctx->gfx_pipeline_state.gfx_prim_mode]);
|
||||
}
|
||||
} else if (ctx->gfx_stages[MESA_SHADER_GEOMETRY] &&
|
||||
ctx->gfx_stages[MESA_SHADER_GEOMETRY]->non_fs.is_generated)
|
||||
|
|
|
|||
|
|
@ -758,7 +758,7 @@ struct zink_shader {
|
|||
union {
|
||||
struct {
|
||||
struct zink_shader *generated_tcs; // a generated shader that this shader "owns"; only valid in the tes stage
|
||||
struct zink_shader *generated_gs; // a generated shader that this shader "owns"
|
||||
struct zink_shader *generated_gs[PIPE_PRIM_MAX]; // generated shaders that this shader "owns"
|
||||
bool is_generated; // if this is a driver-created shader (e.g., tcs)
|
||||
} non_fs;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue