From a510a94b02449c3ecb9fad043a28fc8641ab66c8 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Thu, 2 Jun 2022 10:51:16 -0400 Subject: [PATCH] panfrost: Create transform feedback shaders Valhall has no architectural support for transform feedback. So if a vertex shader uses transform feedback, we need to split the shader into two: a pure vertex stage and a compute-like transform feedback stage. This splitting resembles the splitting we do for IDVS. When compiling a vertex shader that uses transform feedback on Bifrost, also compile the transform feedback variant. That variant (marked by internal=true) will get its stores lowered by the NIR pass introduced earlier in this series. Signed-off-by: Alyssa Rosenzweig Part-of: --- src/gallium/drivers/panfrost/pan_assemble.c | 13 +++++++++++++ src/gallium/drivers/panfrost/pan_context.c | 7 +++++++ src/gallium/drivers/panfrost/pan_context.h | 3 +++ 3 files changed, 23 insertions(+) diff --git a/src/gallium/drivers/panfrost/pan_assemble.c b/src/gallium/drivers/panfrost/pan_assemble.c index 21141e930bd..ae86112b26e 100644 --- a/src/gallium/drivers/panfrost/pan_assemble.c +++ b/src/gallium/drivers/panfrost/pan_assemble.c @@ -47,6 +47,19 @@ panfrost_shader_compile(struct pipe_screen *pscreen, nir_shader *s = nir_shader_clone(NULL, ir); + if (dev->arch >= 6 && s->xfb_info && !s->info.internal) { + /* Create compute shader doing transform feedback */ + nir_shader *xfb = nir_shader_clone(NULL, s); + xfb->info.name = ralloc_asprintf(xfb, "%s@xfb", xfb->info.name); + xfb->info.internal = true; + + state->xfb = calloc(1, sizeof(struct panfrost_shader_state)); + panfrost_shader_compile(pscreen, shader_pool, desc_pool, xfb, state->xfb); + + /* Main shader no longer uses XFB */ + s->info.has_transform_feedback_varyings = false; + } + /* Lower this early so the backends don't have to worry about it */ if (s->info.stage == MESA_SHADER_FRAGMENT) { NIR_PASS_V(s, nir_lower_fragcolor, state->key.fs.nr_cbufs); diff --git a/src/gallium/drivers/panfrost/pan_context.c b/src/gallium/drivers/panfrost/pan_context.c index 3efc48294d6..304107f45c4 100644 --- a/src/gallium/drivers/panfrost/pan_context.c +++ b/src/gallium/drivers/panfrost/pan_context.c @@ -342,6 +342,13 @@ panfrost_delete_shader_state( panfrost_bo_unreference(shader_state->bin.bo); panfrost_bo_unreference(shader_state->state.bo); panfrost_bo_unreference(shader_state->linkage.bo); + + if (shader_state->xfb) { + panfrost_bo_unreference(shader_state->xfb->bin.bo); + panfrost_bo_unreference(shader_state->xfb->state.bo); + panfrost_bo_unreference(shader_state->xfb->linkage.bo); + free(shader_state->xfb); + } } simple_mtx_destroy(&cso->lock); diff --git a/src/gallium/drivers/panfrost/pan_context.h b/src/gallium/drivers/panfrost/pan_context.h index 415ba5f28ed..0145e94e886 100644 --- a/src/gallium/drivers/panfrost/pan_context.h +++ b/src/gallium/drivers/panfrost/pan_context.h @@ -290,6 +290,9 @@ struct panfrost_shader_state { struct pan_shader_info info; + /* Attached transform feedback program, if one exists */ + struct panfrost_shader_state *xfb; + /* Linked varyings, for non-separable programs */ struct pan_linkage linkage;